From f058c2d14245236cb6f706d77391621d008ef683 Mon Sep 17 00:00:00 2001
From: zimoch
Date: Wed, 14 Dec 2011 09:19:54 +0000
Subject: [PATCH] update to 3.14.12.2
---
configure/os/CONFIG_SITE.Common.ios-arm | 28 ++
configure/os/CONFIG_SITE.Common.linux-x86 | 8 +-
configure/os/CONFIG_SITE.Common.linux-x86_64 | 8 +-
src/RTEMS/base/Makefile | 15 +-
src/bpt/Makefile | 3 +-
src/ca/CAref.html | 6 +-
src/ca/Makefile | 2 +-
src/ca/acctst.c | 257 +++++++++++++++++--
src/ca/acctstRegister.cpp | 69 +++++
src/ca/cac.h | 4 +-
src/ca/cadef.h | 3 +-
src/ca/udpiiu.cpp | 19 +-
src/ca/udpiiu.h | 31 ++-
src/cap5/CA.pm | 10 +-
src/cap5/Makefile | 22 +-
src/cas/example/directoryService/Makefile | 4 +-
src/cas/generic/st/casStreamOS.cc | 24 +-
src/catools/caget.c | 28 +-
src/catools/cainfo.c | 6 +-
src/catools/camonitor.c | 136 +++++-----
src/catools/caput.c | 5 +-
src/db/Makefile | 2 -
src/db/dbCAC.h | 6 +-
src/db/dbCommon.dbd | 5 +-
src/db/dbEvent.c | 196 +++++++-------
src/db/dbIocRegister.c | 4 +-
src/db/dbPutNotifyBlocker.cpp | 41 +--
src/db/dbScan.c | 169 ++++++------
src/db/dbScan.h | 10 +-
src/dbStatic/dbExpand.c | 58 +++--
src/dbStatic/dbStaticLib.c | 6 +-
src/dbStatic/dbStaticLib.h | 4 +-
src/dev/softDev/devEventSoft.c | 23 +-
src/excas/Makefile | 4 +-
src/gdd/gdd.cc | 4 +-
src/libCom/Makefile | 2 -
src/libCom/calc/postfix.c | 20 +-
src/libCom/cxxTemplates/epicsSingleton.h | 4 +-
src/libCom/ellLib/ellLib.c | 7 -
src/libCom/error/errlog.c | 23 +-
src/libCom/osi/os/Darwin/osdSock.h | 15 +-
src/libCom/osi/os/Linux/osdSock.h | 13 +-
src/libCom/osi/os/RTEMS/osdSock.h | 13 +-
src/libCom/osi/os/RTEMS/osdTime.cpp | 15 +-
src/libCom/osi/os/WIN32/osdSock.h | 13 +-
src/libCom/osi/os/WIN32/osdThread.c | 6 +-
src/libCom/osi/os/WIN32/osdTime.cpp | 78 ++++--
src/libCom/osi/os/cygwin32/osdSock.h | 12 +-
src/libCom/osi/os/freebsd/osdSock.h | 8 -
src/libCom/osi/os/iOS/osdSock.h | 12 +-
src/libCom/osi/os/posix/epicsMath.h | 5 +
src/libCom/osi/os/posix/osdThread.c | 109 +++++++-
src/libCom/osi/os/solaris/osdSock.h | 12 +-
src/libCom/osi/os/vxWorks/devLibVMEOSD.c | 10 +-
src/libCom/osi/os/vxWorks/osdSock.h | 14 +-
src/libCom/test/Makefile | 8 +-
src/libCom/test/epicsErrlogTest.c | 18 +-
src/libCom/test/macEnvExpandTest.c | 4 +-
src/libCom/timer/timerQueueActiveMgr.cpp | 13 +-
src/makeBaseApp/makeBaseApp.pl | 92 +------
src/makeBaseApp/top/caServerApp/Makefile | 16 +-
src/misc/iocInit.c | 99 ++++++-
src/rec/Makefile | 5 +-
src/rec/calcoutRecord.c | 23 +-
src/rec/calcoutRecord.dbd | 11 +-
src/rec/compressRecord.c | 14 +-
src/rec/compressRecord.dbd | 4 +
src/rec/eventRecord.c | 30 +--
src/rec/eventRecord.dbd | 16 +-
src/softIoc/makeInstallDir.pl | 2 +
src/tools/EPICS/Path.pm | 7 +-
src/tools/convertRelease.pl | 6 +-
src/tools/fullPathName.pl | 4 +-
src/tools/installEpics.pl | 19 +-
src/tools/makeDbDepends.pl | 39 ++-
src/util/iocLogServer.c | 46 ++--
startup/EpicsHostArch | 9 +-
startup/EpicsHostArch.pl | 5 +-
78 files changed, 1228 insertions(+), 873 deletions(-)
create mode 100644 configure/os/CONFIG_SITE.Common.ios-arm
create mode 100644 src/ca/acctstRegister.cpp
diff --git a/configure/os/CONFIG_SITE.Common.ios-arm b/configure/os/CONFIG_SITE.Common.ios-arm
new file mode 100644
index 000000000..89daf1cf9
--- /dev/null
+++ b/configure/os/CONFIG_SITE.Common.ios-arm
@@ -0,0 +1,28 @@
+# CONFIG_SITE.Common.ios-arm
+#
+# Revision-Id: anj@aps.anl.gov-20111202164243-clxybuefflizbyvr
+# This file is maintained by the build community.
+#
+# Site-specific settings for ios-arm target builds
+#-------------------------------------------------------
+
+# Which ARM instruction set(s) to generate code for:
+# Most iOS devices can run programs compiled for both the
+# ARMv6 and ARMv7 instruction sets. ARMv7 code is usually
+# more efficient, but the older devices listed below can only
+# use the ARMv6 instruction set. Including both architectures
+# generates a Universal binary, which is larger and takes
+# longer to compile but runs efficiently on all devices.
+#
+# ARMv6-only devices: iPhone 1 or 3G, iPod Touch Gen 1 or 2
+#
+ARCH_CLASS = armv7
+#ARCH_CLASS = armv6 armv7
+#ARCH_CLASS = armv6
+
+
+# Uncomment these two definitions to use g++ instead of clang++
+# which may be needed in some circumstances:
+#
+#CCC = $(GNU_BIN)/c++
+#GNU_LDLIBS_YES = -lgcc
diff --git a/configure/os/CONFIG_SITE.Common.linux-x86 b/configure/os/CONFIG_SITE.Common.linux-x86
index b404b368c..cb57b0d4a 100644
--- a/configure/os/CONFIG_SITE.Common.linux-x86
+++ b/configure/os/CONFIG_SITE.Common.linux-x86
@@ -1,6 +1,6 @@
# CONFIG_SITE.Common.linux-x86
#
-# Revision-Id: anj@aps.anl.gov-20101122164049-brpnm0uwvpptmw80
+# Revision-Id: anj@aps.anl.gov-20111207195604-heciohzgvyhhpgrb
#
# Site Specific definitions for linux-x86 target
# Only the local epics system manager should modify this file
@@ -33,4 +33,8 @@ COMMANDLINE_LIBRARY = READLINE
#COMMANDLINE_LIBRARY = READLINE_CURSES
-OP_SYS_CFLAGS += -g
+# It makes sense to include debugging symbols even in optimized builds
+# in case you want to attach gdb to the process or examine a core-dump.
+# This does cost disk space, but not memory as debug symbols are not
+# loaded into RAM when the binary is loaded.
+OPT_CFLAGS_YES += -g
diff --git a/configure/os/CONFIG_SITE.Common.linux-x86_64 b/configure/os/CONFIG_SITE.Common.linux-x86_64
index 00dcd1bd2..a69b4a7a2 100644
--- a/configure/os/CONFIG_SITE.Common.linux-x86_64
+++ b/configure/os/CONFIG_SITE.Common.linux-x86_64
@@ -1,6 +1,6 @@
# CONFIG_SITE.Common.linux-x86_64
#
-# Revision-Id: anj@aps.anl.gov-20101122164049-brpnm0uwvpptmw80
+# Revision-Id: anj@aps.anl.gov-20111207195604-heciohzgvyhhpgrb
#
# Site Specific definitions for linux-x86_64 target
# Only the local epics system manager should modify this file
@@ -33,4 +33,8 @@ COMMANDLINE_LIBRARY = READLINE
#COMMANDLINE_LIBRARY = READLINE_CURSES
-OP_SYS_CFLAGS += -g
+# It makes sense to include debugging symbols even in optimized builds
+# in case you want to attach gdb to the process or examine a core-dump.
+# This does cost disk space, but not memory as debug symbols are not
+# loaded into RAM when the binary is loaded.
+OPT_CFLAGS_YES += -g
diff --git a/src/RTEMS/base/Makefile b/src/RTEMS/base/Makefile
index 98d24509f..e77beeeb7 100644
--- a/src/RTEMS/base/Makefile
+++ b/src/RTEMS/base/Makefile
@@ -12,15 +12,14 @@ include $(TOP)/configure/CONFIG
INC += epicsRtemsInitHooks.h
-SRCS += rtems_init.c
-SRCS += rtems_config.c
-SRCS += rtems_netconfig.c
-SRCS += rtems_util.c
-SRCS += setBootConfigFromNVRAM.c
-SRCS += epicsRtemsInitHookPre.c
-SRCS += epicsRtemsInitHookPost.c
+rtemsCom_SRCS += rtems_init.c
+rtemsCom_SRCS += rtems_config.c
+rtemsCom_SRCS += rtems_netconfig.c
+rtemsCom_SRCS += rtems_util.c
+rtemsCom_SRCS += setBootConfigFromNVRAM.c
+rtemsCom_SRCS += epicsRtemsInitHookPre.c
+rtemsCom_SRCS += epicsRtemsInitHookPost.c
LIBRARY_RTEMS = rtemsCom
-LIBRARY_SRCS = $(SRCS) $(BUILD_ARCHS)
include $(TOP)/configure/RULES
diff --git a/src/bpt/Makefile b/src/bpt/Makefile
index f78b13d98..231c1b105 100644
--- a/src/bpt/Makefile
+++ b/src/bpt/Makefile
@@ -22,7 +22,8 @@ DBD += bptTypeKdegF.dbd
PROD_LIBS = Com
PROD_HOST += makeBpt
-makeBpt_SRCS=makeBpt
+
+makeBpt_SRCS = makeBpt
include $(TOP)/configure/RULES
diff --git a/src/ca/CAref.html b/src/ca/CAref.html
index 17855839e..185eedd3b 100644
--- a/src/ca/CAref.html
+++ b/src/ca/CAref.html
@@ -52,7 +52,7 @@ src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01!" height="31"
width="88">
Modified on
-Date: Wed 2010-11-24 13:31:47 -0500
+Date: Tue 2011-07-26 10:40:37 -0600
Table of Contents
@@ -246,7 +246,7 @@ Date: Wed 2010-11-24 13:31:47 -0500
Why Reconfigure Channel Access
-Typically reasons to reconfigure EPICS Channel Access:
+Typical reasons to reconfigure EPICS Channel Access:
- Two independent control systems must share a network without fear of
interaction
@@ -4359,7 +4359,7 @@ that use ca_context_destroy).
ca_context_destroy()
-
void ca_dump_dbr (chtype TYPE, unsigned COUNT, const void * PDBR);
+void ca_dump_dbr (chtype TYPE, unsigned COUNT, const void * PDBR);
Description
diff --git a/src/ca/Makefile b/src/ca/Makefile
index db4186d16..45eb8ee48 100644
--- a/src/ca/Makefile
+++ b/src/ca/Makefile
@@ -92,7 +92,7 @@ PROD_LIBS = ca Com
PROD_SYS_LIBS_WIN32 = ws2_32 advapi32 user32
PROD_HOST += caRepeater catime acctst caConnTest casw caEventRate
-OBJS_IOC_vxWorks += catime acctst caConnTest casw caEventRate
+OBJS_IOC += catime acctst caConnTest casw caEventRate acctstRegister
caRepeater_SRCS = caRepeater.cpp
catime_SRCS = catimeMain.c catime.c
acctst_SRCS = acctstMain.c acctst.c
diff --git a/src/ca/acctst.c b/src/ca/acctst.c
index 9c4840996..f2d102868 100644
--- a/src/ca/acctst.c
+++ b/src/ca/acctst.c
@@ -10,6 +10,10 @@
/*
* CA regression test
+ * Authors:
+ * Jeff Hill
+ * Murali Shankar - initial versions of verifyMultithreadSubscr
+ *
*/
/*
@@ -26,6 +30,8 @@
*/
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
#include "epicsAssert.h"
+#include "epicsMutex.h"
+#include "epicsEvent.h"
#include "epicsTime.h"
#include "dbDefs.h"
#include "envDefs.h"
@@ -2719,6 +2725,186 @@ void fdRegCB ( void * parg, int fd, int opened )
}
}
+typedef struct {
+ char m_chanName[100u];
+ struct ca_client_context * m_pCtx;
+ chid m_chan;
+ epicsMutexId m_mutex;
+ epicsEventId m_testCompleteEvent;
+ epicsEventId m_threadExitEvent;
+ size_t m_nUpdatesReceived;
+ size_t m_nUpdatesRequired;
+ int m_testInitiated;
+ int m_testComplete;
+ unsigned m_interestLevel;
+} MultiThreadSubscrTest;
+
+static void testMultithreadSubscrSubscrCallback
+ ( struct event_handler_args eha )
+{
+ const epicsEventId firstUpdateEvent = ( epicsEventId ) eha.usr;
+ epicsEventSignal ( firstUpdateEvent );
+}
+
+static void testMultithreadSubscrCreateSubscr ( void * pParm )
+{
+ static unsigned nElem = 0;
+ int testComplete = FALSE;
+ evid id;
+ epicsEventId firstUpdateEvent;
+ epicsEventWaitStatus eventWaitStatus;
+ MultiThreadSubscrTest * const pMultiThreadSubscrTest =
+ ( MultiThreadSubscrTest * ) pParm;
+
+ /* this is required for the ca_flush below to work correctly */
+ int status = ca_attach_context ( pMultiThreadSubscrTest->m_pCtx );
+ verify ( status == ECA_NORMAL );
+ firstUpdateEvent = epicsEventMustCreate ( epicsEventEmpty );
+ verify ( firstUpdateEvent );
+ status = ca_create_subscription (
+ DBR_TIME_LONG,
+ nElem,
+ pMultiThreadSubscrTest->m_chan,
+ DBE_VALUE,
+ testMultithreadSubscrSubscrCallback,
+ firstUpdateEvent,
+ & id );
+ verify ( status == ECA_NORMAL );
+ status = ca_flush_io ();
+ verify ( status == ECA_NORMAL );
+ /* wait for first update */
+ eventWaitStatus = epicsEventWaitWithTimeout (
+ firstUpdateEvent, 60.0 * 10 );
+ verify ( eventWaitStatus == epicsEventWaitOK );
+ epicsEventDestroy ( firstUpdateEvent );
+ status = ca_clear_subscription ( id );
+ verify ( status == ECA_NORMAL );
+ epicsMutexMustLock ( pMultiThreadSubscrTest->m_mutex );
+ pMultiThreadSubscrTest->m_nUpdatesReceived++;
+ testComplete = ( pMultiThreadSubscrTest->m_nUpdatesReceived ==
+ pMultiThreadSubscrTest->m_nUpdatesRequired );
+ pMultiThreadSubscrTest->m_testComplete = testComplete;
+ epicsMutexUnlock ( pMultiThreadSubscrTest->m_mutex );
+ if ( testComplete ) {
+ epicsEventSignal ( pMultiThreadSubscrTest->m_testCompleteEvent );
+ }
+}
+
+void testMultithreadSubscrConnHandler ( struct connection_handler_args args )
+{
+ MultiThreadSubscrTest * const pMultiThreadSubscrTest =
+ ( MultiThreadSubscrTest * ) ca_puser ( args.chid );
+ epicsMutexMustLock ( pMultiThreadSubscrTest->m_mutex );
+ if ( !pMultiThreadSubscrTest->m_testInitiated &&
+ args.op == CA_OP_CONN_UP ) {
+ int i;
+ pMultiThreadSubscrTest->m_testInitiated = TRUE;
+ for ( i = 0; i < pMultiThreadSubscrTest->m_nUpdatesRequired; i++ ) {
+ char threadname[64];
+ epicsThreadId threadId;
+ sprintf(threadname, "testSubscr%06u", i);
+ threadId = epicsThreadCreate ( threadname,
+ epicsThreadPriorityMedium,
+ epicsThreadGetStackSize(epicsThreadStackSmall),
+ testMultithreadSubscrCreateSubscr,
+ pMultiThreadSubscrTest );
+ verify ( threadId );
+ }
+ }
+ epicsMutexUnlock ( pMultiThreadSubscrTest->m_mutex );
+}
+
+void testMultithreadSubscr ( void * pParm )
+{
+ MultiThreadSubscrTest * const pMultiThreadSubscrTest =
+ ( MultiThreadSubscrTest * ) pParm;
+ int status;
+ unsigned i;
+
+ status = ca_context_create ( ca_enable_preemptive_callback );
+ verify ( status == ECA_NORMAL );
+ pMultiThreadSubscrTest->m_pCtx = ca_current_context ();
+ verify ( pMultiThreadSubscrTest->m_pCtx );
+ status = ca_create_channel (
+ pMultiThreadSubscrTest->m_chanName,
+ testMultithreadSubscrConnHandler,
+ pMultiThreadSubscrTest,
+ CA_PRIORITY_MIN,
+ & pMultiThreadSubscrTest->m_chan );
+ verify ( status == ECA_NORMAL );
+
+ showProgressBegin ( "verifyMultithreadSubscr",
+ pMultiThreadSubscrTest->m_interestLevel );
+ i = 0;
+ while ( TRUE ) {
+ int success = FALSE;
+ epicsEventWaitStatus eventWaitStatus;
+ epicsMutexMustLock ( pMultiThreadSubscrTest->m_mutex );
+ success = pMultiThreadSubscrTest->m_testComplete;
+ epicsMutexUnlock ( pMultiThreadSubscrTest->m_mutex );
+ if ( success ) {
+ break;
+ }
+ eventWaitStatus = epicsEventWaitWithTimeout (
+ pMultiThreadSubscrTest->m_testCompleteEvent, 0.1 );
+ verify ( eventWaitStatus == epicsEventWaitOK ||
+ eventWaitStatus == epicsEventWaitTimeout );
+ if ( i++ % 100 == 0u )
+ showProgress ( pMultiThreadSubscrTest->m_interestLevel );
+ verify ( i < 1000 );
+ }
+ showProgressEnd ( pMultiThreadSubscrTest->m_interestLevel );
+
+ status = ca_clear_channel ( pMultiThreadSubscrTest->m_chan );
+ verify ( status == ECA_NORMAL );
+ ca_context_destroy ();
+ epicsEventSignal ( pMultiThreadSubscrTest->m_threadExitEvent );
+}
+
+/*
+ * test installation of subscriptions similar to usage paterns
+ * employed by modern versions of the sequencer
+ */
+void verifyMultithreadSubscr ( const char * pName, unsigned interestLevel )
+{
+ static unsigned nSubscr = 3000;
+ epicsThreadId threadId;
+ MultiThreadSubscrTest * const pMultiThreadSubscrTest =
+ (MultiThreadSubscrTest*) calloc ( 1,
+ sizeof ( MultiThreadSubscrTest ) );
+ verify ( pMultiThreadSubscrTest);
+ pMultiThreadSubscrTest->m_mutex = epicsMutexMustCreate ();
+ verify ( pMultiThreadSubscrTest->m_mutex );
+ pMultiThreadSubscrTest->m_testCompleteEvent =
+ epicsEventMustCreate ( epicsEventEmpty );
+ verify ( pMultiThreadSubscrTest->m_testCompleteEvent );
+ pMultiThreadSubscrTest->m_threadExitEvent =
+ epicsEventMustCreate ( epicsEventEmpty );
+ verify ( pMultiThreadSubscrTest->m_threadExitEvent );
+ strncpy ( pMultiThreadSubscrTest->m_chanName, pName,
+ sizeof ( pMultiThreadSubscrTest->m_chanName ) );
+ pMultiThreadSubscrTest->m_chanName
+ [ sizeof ( pMultiThreadSubscrTest->m_chanName ) - 1u ] = '\0';
+ pMultiThreadSubscrTest->m_nUpdatesRequired = nSubscr;
+ pMultiThreadSubscrTest->m_interestLevel = interestLevel;
+ threadId = epicsThreadCreate (
+ "testMultithreadSubscr",
+ epicsThreadPriorityMedium,
+ epicsThreadGetStackSize(epicsThreadStackSmall),
+ testMultithreadSubscr, pMultiThreadSubscrTest );
+ verify ( threadId );
+ {
+ epicsEventWaitStatus eventWaitStatus;
+ eventWaitStatus = epicsEventWaitWithTimeout (
+ pMultiThreadSubscrTest->m_threadExitEvent, 1000.0 );
+ verify ( eventWaitStatus == epicsEventWaitOK );
+ }
+ epicsEventDestroy ( pMultiThreadSubscrTest->m_testCompleteEvent );
+ epicsEventDestroy ( pMultiThreadSubscrTest->m_threadExitEvent );
+ epicsMutexDestroy ( pMultiThreadSubscrTest->m_mutex );
+ free ( pMultiThreadSubscrTest );
+}
+
void fdManagerVerify ( const char * pName, unsigned interestLevel )
{
int status;
@@ -2965,17 +3151,22 @@ void verifyContextRundownFlush ( const char * pName, unsigned interestLevel )
SEVCHK ( status, "context create failed" );
status = ca_create_channel ( pName, 0, 0, 0, & chan );
- SEVCHK ( status, NULL );
-
- status = ca_pend_io( timeoutToPendIO );
- SEVCHK ( status, "channel connect failed" );
-
- status = ca_put ( DBR_DOUBLE, chan, & stim );
- SEVCHK ( status, "channel put failed" );
-
- status = ca_clear_channel ( chan );
- SEVCHK ( status, NULL );
-
+ /*
+ * currently in-memory channels cant be used with this test
+ * !!!! FIX ME, FIX ME, FIX ME, FIX ME !!!!
+ */
+ if ( status != ECA_UNAVAILINSERV ) {
+ SEVCHK ( status, NULL );
+
+ status = ca_pend_io( timeoutToPendIO );
+ SEVCHK ( status, "channel connect failed" );
+
+ status = ca_put ( DBR_DOUBLE, chan, & stim );
+ SEVCHK ( status, "channel put failed" );
+
+ status = ca_clear_channel ( chan );
+ SEVCHK ( status, NULL );
+ }
ca_context_destroy ();
}
@@ -2985,24 +3176,28 @@ void verifyContextRundownFlush ( const char * pName, unsigned interestLevel )
dbr_double_t resp;
status = ca_context_create ( ca_disable_preemptive_callback );
SEVCHK ( status, "context create failed" );
-
+
status = ca_create_channel ( pName, 0, 0, 0, & chan );
SEVCHK ( status, NULL );
-
- status = ca_pend_io( timeoutToPendIO );
- SEVCHK ( status, "channel connect failed" );
-
- status = ca_get ( DBR_DOUBLE, chan, & resp );
- SEVCHK ( status, "channel get failed" );
-
- status = ca_pend_io ( timeoutToPendIO );
- SEVCHK ( status, "get, pend io failed" );
-
- verify ( stim == resp );
-
- status = ca_clear_channel ( chan );
- SEVCHK ( status, NULL );
-
+ /*
+ * currently in-memory channels cant be used with this test
+ * !!!! FIX ME, FIX ME, FIX ME, FIX ME !!!!
+ */
+ if ( status != ECA_UNAVAILINSERV ) {
+ status = ca_pend_io( timeoutToPendIO );
+ SEVCHK ( status, "channel connect failed" );
+
+ status = ca_get ( DBR_DOUBLE, chan, & resp );
+ SEVCHK ( status, "channel get failed" );
+
+ status = ca_pend_io ( timeoutToPendIO );
+ SEVCHK ( status, "get, pend io failed" );
+
+ verify ( stim == resp );
+
+ status = ca_clear_channel ( chan );
+ SEVCHK ( status, NULL );
+ }
ca_context_destroy ();
}
@@ -3028,6 +3223,13 @@ void verifyContextRundownChanStillExist (
for ( i = 0; i < NELEMENTS ( chan ); i++ ) {
status = ca_create_channel ( pName, 0, 0, 0, & chan[i] );
+ /*
+ * currently in-memory channels cant be used with this test
+ * !!!! FIX ME, FIX ME, FIX ME, FIX ME !!!!
+ */
+ if ( status == ECA_UNAVAILINSERV ) {
+ break;
+ }
SEVCHK ( status, NULL );
}
@@ -3123,6 +3325,7 @@ int acctst ( const char * pName, unsigned interestLevel, unsigned channelCount,
verifyHighThroughputReadCallback ( chan, interestLevel );
verifyHighThroughputWriteCallback ( chan, interestLevel );
verifyBadString ( chan, interestLevel );
+ verifyMultithreadSubscr ( pName, interestLevel );
if ( select != ca_enable_preemptive_callback ) {
fdManagerVerify ( pName, interestLevel );
}
diff --git a/src/ca/acctstRegister.cpp b/src/ca/acctstRegister.cpp
new file mode 100644
index 000000000..e75ed7fe3
--- /dev/null
+++ b/src/ca/acctstRegister.cpp
@@ -0,0 +1,69 @@
+/*************************************************************************\
+* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
+* National Laboratory.
+* Copyright (c) 2002 The Regents of the University of California, as
+* Operator of Los Alamos National Laboratory.
+* EPICS BASE is distributed subject to a Software License Agreement found
+* in file LICENSE that is included with this distribution.
+\*************************************************************************/
+
+/*
+ * CA client library diagnostics IOC shell registration
+ * Authors:
+ * Jeff Hill
+ */
+
+#include
+#include "caDiagnostics.h"
+
+/* Information needed by iocsh */
+static const iocshArg acctstArg0 = { "channel name", iocshArgString };
+static const iocshArg acctstArg1 = { "interest level", iocshArgInt };
+static const iocshArg acctstArg2 = { "channel count", iocshArgInt };
+static const iocshArg acctstArg3 = { "repetition count", iocshArgInt };
+static const iocshArg acctstArg4 = { "preemptive callback select", iocshArgInt };
+
+static const iocshArg *acctstArgs[] =
+{
+ &acctstArg0,
+ &acctstArg1,
+ &acctstArg2,
+ &acctstArg3,
+ &acctstArg4
+};
+static const iocshFuncDef acctstFuncDef = {"acctst", 5, acctstArgs};
+
+
+/* Wrapper called by iocsh, selects the argument types that print needs */
+static void acctstCallFunc(const iocshArgBuf *args) {
+ if ( args[1].ival < 0 ) {
+ printf ( "negative interest level not allowed\n" );
+ return;
+ }
+ if ( args[2].ival < 0 ) {
+ printf ( "negative channel count not allowed\n" );
+ return;
+ }
+ if ( args[3].ival < 0 ) {
+ printf ( "negative repetition count not allowed\n" );
+ return;
+ }
+ acctst (
+ args[0].sval, /* channel name */
+ ( unsigned ) args[1].ival, /* interest level */
+ ( unsigned ) args[2].ival, /* channel count */
+ ( unsigned ) args[3].ival, /* repetition count */
+ ( ca_preemptive_callback_select ) args[4].ival ); /* preemptive callback select */
+}
+
+struct AutoInit {
+ AutoInit ();
+};
+
+AutoInit :: AutoInit ()
+{
+ iocshRegister ( &acctstFuncDef, acctstCallFunc );
+}
+
+AutoInit autoInit;
+
diff --git a/src/ca/cac.h b/src/ca/cac.h
index 4bac0cdb1..ae20eef27 100644
--- a/src/ca/cac.h
+++ b/src/ca/cac.h
@@ -266,8 +266,8 @@ private:
// **** lock hierarchy ****
// 1) callback lock must always be acquired before
// the primary mutex if both locks are needed
- mutable epicsMutex & mutex;
- mutable epicsMutex & cbMutex;
+ epicsMutex & mutex;
+ epicsMutex & cbMutex;
epicsEvent iiuUninstall;
ipAddrToAsciiEngine & ipToAEngine;
epicsTimerQueueActive & timerQueue;
diff --git a/src/ca/cadef.h b/src/ca/cadef.h
index 7095512e3..e62dd7249 100644
--- a/src/ca/cadef.h
+++ b/src/ca/cadef.h
@@ -185,7 +185,8 @@ epicsShareFunc enum channel_state epicsShareAPI ca_state (chid chan);
epicsShareFunc int epicsShareAPI ca_task_initialize (void);
enum ca_preemptive_callback_select
{ ca_disable_preemptive_callback, ca_enable_preemptive_callback };
-epicsShareFunc int epicsShareAPI ca_context_create (enum ca_preemptive_callback_select select);
+epicsShareFunc int epicsShareAPI
+ ca_context_create (enum ca_preemptive_callback_select select);
epicsShareFunc void epicsShareAPI ca_detach_context ();
/************************************************************************/
diff --git a/src/ca/udpiiu.cpp b/src/ca/udpiiu.cpp
index 755875aa7..625bead9f 100644
--- a/src/ca/udpiiu.cpp
+++ b/src/ca/udpiiu.cpp
@@ -81,8 +81,9 @@ udpiiu::udpiiu (
cac::lowestPriorityLevelAbove (
cac::lowestPriorityLevelAbove (
cac.getInitializingThreadsPriority () ) ) ),
+ m_repeaterTimerNotify ( *this ),
repeaterSubscribeTmr (
- *this, timerQueue, cbMutexIn, ctxNotifyIn ),
+ m_repeaterTimerNotify, timerQueue, cbMutexIn, ctxNotifyIn ),
govTmr ( *this, timerQueue, cacMutexIn ),
maxPeriod ( maxSearchPeriodDefault ),
rtteMean ( minRoundTripEstimate ),
@@ -397,14 +398,14 @@ void udpRecvThread::run ()
}
/*
- * udpiiu::repeaterRegistrationMessage ()
+ * udpiiu::M_repeaterTimerNotify::repeaterRegistrationMessage ()
*
* register with the repeater
*/
-void udpiiu::repeaterRegistrationMessage ( unsigned attemptNumber )
+void udpiiu :: M_repeaterTimerNotify :: repeaterRegistrationMessage ( unsigned attemptNumber )
{
- epicsGuard < epicsMutex > cbGuard ( this->cacMutex );
- caRepeaterRegistrationMessage ( this->sock, this->repeaterPort, attemptNumber );
+ epicsGuard < epicsMutex > cbGuard ( m_udpiiu.cacMutex );
+ caRepeaterRegistrationMessage ( m_udpiiu.sock, m_udpiiu.repeaterPort, attemptNumber );
}
/*
@@ -1233,16 +1234,16 @@ void udpiiu::govExpireNotify (
this->ppSearchTmr[0]->installChannel ( guard, chan );
}
-int udpiiu :: printFormated (
- epicsGuard < epicsMutex > & cbGuard,
- const char * pformat, ... )
+int udpiiu :: M_repeaterTimerNotify :: printFormated (
+ epicsGuard < epicsMutex > & cbGuard,
+ const char * pformat, ... )
{
va_list theArgs;
int status;
va_start ( theArgs, pformat );
- status = this->cacRef.varArgsPrintFormated ( cbGuard, pformat, theArgs );
+ status = m_udpiiu.cacRef.varArgsPrintFormated ( cbGuard, pformat, theArgs );
va_end ( theArgs );
diff --git a/src/ca/udpiiu.h b/src/ca/udpiiu.h
index 0f3d1a313..2f9918e49 100644
--- a/src/ca/udpiiu.h
+++ b/src/ca/udpiiu.h
@@ -88,8 +88,7 @@ static const double beaconAnomalySearchPeriod = 5.0; // seconds
class udpiiu :
private netiiu,
private searchTimerNotify,
- private disconnectGovernorNotify,
- private repeaterTimerNotify {
+ private disconnectGovernorNotify {
public:
udpiiu (
epicsGuard < epicsMutex > & cacGuard,
@@ -139,9 +138,24 @@ private:
private:
udpiiu & _udpiiu;
};
+ class M_repeaterTimerNotify :
+ public repeaterTimerNotify {
+ public:
+ M_repeaterTimerNotify ( udpiiu & iiu ) :
+ m_udpiiu ( iiu ) {}
+ // repeaterTimerNotify
+ void repeaterRegistrationMessage (
+ unsigned attemptNumber );
+ int printFormated (
+ epicsGuard < epicsMutex > & callbackControl,
+ const char * pformat, ... );
+ private:
+ udpiiu & m_udpiiu;
+ };
char xmitBuf [MAX_UDP_SEND];
char recvBuf [MAX_UDP_RECV];
udpRecvThread recvThread;
+ M_repeaterTimerNotify m_repeaterTimerNotify;
repeaterSubscribeTimer repeaterSubscribeTmr;
disconnectGovernorTimer govTmr;
tsDLList < SearchDest > _searchDestList;
@@ -149,8 +163,8 @@ private:
double rtteMean;
double rtteMeanDev;
cac & cacRef;
- mutable epicsMutex & cbMutex;
- mutable epicsMutex & cacMutex;
+ epicsMutex & cbMutex;
+ epicsMutex & cacMutex;
epics_auto_ptr < epics_auto_ptr < class searchTimer >, eapt_array > ppSearchTmr;
unsigned nBytesInXmitBuf;
unsigned nTimers;
@@ -278,14 +292,6 @@ private:
void govExpireNotify (
epicsGuard < epicsMutex > &, nciu & );
- // repeaterTimerNotify
- void repeaterRegistrationMessage (
- unsigned attemptNumber );
-
- int printFormated (
- epicsGuard < epicsMutex > & callbackControl,
- const char * pformat, ... );
-
udpiiu ( const udpiiu & );
udpiiu & operator = ( const udpiiu & );
@@ -294,6 +300,7 @@ private:
// These are needed for the vxWorks 5.5 compiler:
friend class udpiiu::SearchDestUDP;
friend class udpiiu::SearchRespCallback;
+ friend class udpiiu::M_repeaterTimerNotify;
};
#endif // udpiiuh
diff --git a/src/cap5/CA.pm b/src/cap5/CA.pm
index 3aa7c7f51..ac6542e01 100644
--- a/src/cap5/CA.pm
+++ b/src/cap5/CA.pm
@@ -6,9 +6,6 @@ use warnings;
my $version = '0.4';
-exists $ENV{EPICS_HOST_ARCH}
- or die "EPICS_HOST_ARCH environment variable not set";
-
package CA;
@@ -26,12 +23,17 @@ package Cap5;
our $VERSION = $version;
our @ISA = qw(DynaLoader);
+# Library is specific to the Perl version and archname
+use Config;
+my $perl_version = $Config::Config{version};
+my $perl_archname = $Config::Config{archname};
+
require DynaLoader;
# Add our lib/ directory to the shared library search path
use File::Basename;
my $Lib = dirname(__FILE__);
-push @DynaLoader::dl_library_path, "$Lib/../$ENV{EPICS_HOST_ARCH}";
+push @DynaLoader::dl_library_path, "$Lib/$perl_version/$perl_archname";
bootstrap Cap5 $VERSION;
diff --git a/src/cap5/Makefile b/src/cap5/Makefile
index 6d58dcfd6..4707c1621 100644
--- a/src/cap5/Makefile
+++ b/src/cap5/Makefile
@@ -22,8 +22,12 @@ ifneq ($(findstring darwin,$(T_A)),)
LOADABLE_SHRLIB_SUFFIX = .bundle
endif
-ifeq ($(T_A),$(EPICS_HOST_ARCH))
-ifeq ($(findstring $(OS_CLASS),WIN32 cygwin32 solaris-sparc),)
+PERL_VERSION = $(shell $(PERL) ../perlConfig.pl version)
+PERL_ARCHNAME = $(shell $(PERL) ../perlConfig.pl archname)
+PERL_ARCHPATH = $(PERL_VERSION)/$(PERL_ARCHNAME)
+
+ifeq ($(findstring Host,$(VALID_BUILDS)),Host)
+ifeq ($(findstring $(OS_CLASS),WIN32 cygwin32),)
# Doesn't build on WIN32
LOADABLE_LIBRARY_HOST = Cap5
@@ -34,6 +38,10 @@ ifeq ($(findstring $(OS_CLASS),WIN32 cygwin32 solaris-sparc),)
PERL_SCRIPTS += camonitor.pl
PERL_MODULES += CA.pm
+ PERL_MODULES += $(PERL_ARCHPATH)/$(LOADABLE_SHRLIB_PREFIX)Cap5$(LOADABLE_SHRLIB_SUFFIX)
+
+ HTMLS_DIR = .
+ HTMLS = CA.html
endif
endif
@@ -42,12 +50,6 @@ Cap5_LIBS = ca Com
Cap5_INCLUDES = -I$(shell $(PERL) ../perlConfig.pl archlib)/CORE
Cap5_CFLAGS = $(shell $(PERL) ../perlConfig.pl ccflags)
-ifeq ($(findstring Host,$(VALID_BUILDS)),Host)
- # Can only create docs in Host build
- HTMLS_DIR = .
- HTMLS = CA.html
-endif
-
include $(TOP)/configure/RULES
ifdef T_A
@@ -61,6 +63,10 @@ ifdef T_A
$(RM) $@
podchecker $< && pod2html --infile=$< --outfile=$@
+ $(INSTALL_PERL_MODULES)/$(PERL_ARCHPATH)/%: %
+ $(ECHO) "Installing loadable shared library $@"
+ @$(INSTALL_LIBRARY) -d -m $(LIB_PERMISSIONS) $< $(INSTALL_PERL_MODULES)/$(PERL_ARCHPATH)
+
clean::
$(RM) Cap5.c
endif
diff --git a/src/cas/example/directoryService/Makefile b/src/cas/example/directoryService/Makefile
index d6b4aefb7..af38f906a 100644
--- a/src/cas/example/directoryService/Makefile
+++ b/src/cas/example/directoryService/Makefile
@@ -23,8 +23,8 @@ PROD_LIBS := cas ca gdd Com
#
PROD_SYS_LIBS_WIN32 := ws2_32 advapi32 user32
-SRCS += main.cc
-SRCS += directoryServer.cc
+caDirServ_SRCS += main.cc
+caDirServ_SRCS += directoryServer.cc
PROD_HOST = caDirServ
diff --git a/src/cas/generic/st/casStreamOS.cc b/src/cas/generic/st/casStreamOS.cc
index 9d069644b..afb17fb8a 100644
--- a/src/cas/generic/st/casStreamOS.cc
+++ b/src/cas/generic/st/casStreamOS.cc
@@ -64,18 +64,6 @@ private:
casStreamReadReg & operator = ( const casStreamReadReg & );
};
-//
-// casStreamOS::armRecv ()
-//
-inline void casStreamOS::armRecv()
-{
- if ( ! this->pRdReg ) {
- if ( ! this->inBufFull() ) {
- this->pRdReg = new casStreamReadReg ( *this );
- }
- }
-}
-
//
// casStreamReadReg::casStreamReadReg()
//
@@ -309,6 +297,18 @@ void casStreamIOWakeup::start ( casStreamOS &os )
this->pOS->printStatus ( "casStreamIOWakeup tmr start" );
}
+//
+// casStreamOS::armRecv ()
+//
+inline void casStreamOS::armRecv()
+{
+ if ( ! this->pRdReg ) {
+ if ( ! this->inBufFull() ) {
+ this->pRdReg = new casStreamReadReg ( *this );
+ }
+ }
+}
+
//
// casStreamOS::disarmRecv ()
//
diff --git a/src/catools/caget.c b/src/catools/caget.c
index 1ce588615..a2b0e08b0 100644
--- a/src/catools/caget.c
+++ b/src/catools/caget.c
@@ -126,7 +126,6 @@ static void event_handler (evargs args)
ppv->dbrType = args.type;
ppv->value = calloc(1, dbr_size_n(args.type, args.count));
memcpy(ppv->value, args.dbr, dbr_size_n(args.type, args.count));
- ppv->onceConnected = 1;
ppv->nElems = args.count;
nRead++;
}
@@ -159,12 +158,13 @@ static int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
int n, result;
for (n = 0; n < nPvs; n++) {
+ unsigned long nElems;
/* Set up pvs structure */
/* -------------------- */
/* Get natural type and array count */
- pvs[n].nElems = ca_element_count(pvs[n].chid);
+ nElems = ca_element_count(pvs[n].chid);
pvs[n].dbfType = ca_field_type(pvs[n].chid);
pvs[n].dbrType = dbrType;
@@ -183,10 +183,6 @@ static int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
pvs[n].dbrType = DBR_TIME_STRING;
}
}
- /* Adjust array count */
- if (reqElems > pvs[n].nElems)
- reqElems = pvs[n].nElems;
- pvs[n].reqElems = reqElems;
/* Issue CA request */
/* ---------------- */
@@ -196,17 +192,20 @@ static int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
nConn++;
pvs[n].onceConnected = 1;
if (request == callback)
- { /* Event handler will allocate value */
+ {
+ /* Event handler will allocate value and set nElems */
+ pvs[n].reqElems = reqElems > nElems ? nElems : reqElems;
result = ca_array_get_callback(pvs[n].dbrType,
pvs[n].reqElems,
pvs[n].chid,
event_handler,
(void*)&pvs[n]);
} else {
- /* Allocate value structure */
+ /* We allocate value structure and set nElems */
+ pvs[n].nElems = reqElems && reqElems < nElems ? reqElems : nElems;
pvs[n].value = calloc(1, dbr_size_n(pvs[n].dbrType, pvs[n].nElems));
- if(!pvs[n].value) {
- fprintf(stderr,"Allocation failed\n");
+ if (!pvs[n].value) {
+ fprintf(stderr,"Memory allocation failed\n");
return 1;
}
result = ca_array_get(pvs[n].dbrType,
@@ -252,9 +251,6 @@ static int caget (pv *pvs, int nPvs, RequestT request, OutputT format,
/* -------------- */
for (n = 0; n < nPvs; n++) {
- /* Truncate the data printed to what was requested. */
- if (pvs[n].reqElems != 0 && pvs[n].nElems > pvs[n].reqElems)
- pvs[n].nElems = pvs[n].reqElems;
switch (format) {
case plain: /* Emulate old caget behaviour */
@@ -377,7 +373,7 @@ static void complainIfNotPlainAndSet (OutputT *current, const OutputT requested)
int main (int argc, char *argv[])
{
- int n = 0;
+ int n;
int result; /* CA result */
OutputT format = plain; /* User specified format */
RequestT request = get; /* User specified request type */
@@ -389,7 +385,7 @@ int main (int argc, char *argv[])
int digits = 0; /* getopt() no. of float digits */
int nPvs; /* Number of PVs */
- pv* pvs = 0; /* Array of PV structures */
+ pv* pvs; /* Array of PV structures */
LINE_BUFFER(stdout); /* Configure stdout buffering */
@@ -529,7 +525,7 @@ int main (int argc, char *argv[])
result = ca_context_create(ca_disable_preemptive_callback);
if (result != ECA_NORMAL) {
fprintf(stderr, "CA error %s occurred while trying "
- "to start channel access '%s'.\n", ca_message(result), pvs[n].name);
+ "to start channel access.\n", ca_message(result));
return 1;
}
/* Allocate PV structure array */
diff --git a/src/catools/cainfo.c b/src/catools/cainfo.c
index a287f6984..924c34b10 100644
--- a/src/catools/cainfo.c
+++ b/src/catools/cainfo.c
@@ -127,13 +127,13 @@ int cainfo (pv *pvs, int nPvs)
int main (int argc, char *argv[])
{
- int n = 0;
+ int n;
int result; /* CA result */
int opt; /* getopt() current option */
int nPvs; /* Number of PVs */
- pv* pvs = 0; /* Array of PV structures */
+ pv* pvs; /* Array of PV structures */
LINE_BUFFER(stdout); /* Configure stdout buffering */
@@ -195,7 +195,7 @@ int main (int argc, char *argv[])
result = ca_context_create(ca_disable_preemptive_callback);
if (result != ECA_NORMAL) {
fprintf(stderr, "CA error %s occurred while trying "
- "to start channel access '%s'.\n", ca_message(result), pvs[n].name);
+ "to start channel access.\n", ca_message(result));
return 1;
}
/* Allocate PV structure array */
diff --git a/src/catools/camonitor.c b/src/catools/camonitor.c
index 617ee7622..307dad8d6 100644
--- a/src/catools/camonitor.c
+++ b/src/catools/camonitor.c
@@ -42,45 +42,49 @@ static int nConn = 0; /* Number of connected
void usage (void)
{
- fprintf (stderr, "\nUsage: camonitor [options] ...\n\n"
- " -h: Help: Print this message\n"
+ fprintf (stderr, "\nUsage: camonitor [options] ...\n"
+ "\n"
+ " -h: Help; Print this message\n"
"Channel Access options:\n"
- " -w : Wait time, specifies CA timeout, default is %f second(s)\n"
- " -m : Specify CA event mask to use, with being any combination of\n"
- " 'v' (value), 'a' (alarm), 'l' (log/archive), 'p' (property). Default: va\n"
- " -p : CA priority (0-%u, default 0=lowest)\n"
+ " -w : Wait time, specifies CA timeout, default is %f second(s)\n"
+ " -m : Specify CA event mask to use. is any combination of\n"
+ " 'v' (value), 'a' (alarm), 'l' (log/archive), 'p' (property).\n"
+ " Default event mask is 'va'\n"
+ " -p : CA priority (0-%u, default 0=lowest)\n"
"Timestamps:\n"
- " Default: Print absolute timestamps (as reported by CA server)\n"
- " -t : Specify timestamp source(s) and type, with containing\n"
- " 's' = CA server (remote) timestamps\n"
- " 'c' = CA client (local) timestamps (shown in '()'s)\n"
- " 'n' = no timestamps\n"
- " 'r' = relative timestamps (time elapsed since start of program)\n"
- " 'i' = incremental timestamps (time elapsed since last update)\n"
- " 'I' = incremental timestamps (time elapsed since last update, by channel)\n"
+ " Default: Print absolute timestamps (as reported by CA server)\n"
+ " -t : Specify timestamp source(s) and type, with containing\n"
+ " 's' = CA server (remote) timestamps\n"
+ " 'c' = CA client (local) timestamps (shown in '()'s)\n"
+ " 'n' = no timestamps\n"
+ " 'r' = relative timestamps (time elapsed since start of program)\n"
+ " 'i' = incremental timestamps (time elapsed since last update)\n"
+ " 'I' = incremental timestamps (time since last update, by channel)\n"
+ " 'r', 'i' or 'I' require 's' or 'c' to select the time source\n"
"Enum format:\n"
- " -n: Print DBF_ENUM values as number (default are enum string values)\n"
- "Arrays: Value format: print number of requested values, then list of values\n"
- " Default: Print all values\n"
- " -# : Print first elements of an array\n"
- " -S: Print array of char as a string (long string)\n"
- "Floating point type format:\n"
- " Default: Use %%g format\n"
- " -e : Use %%e format, with a precision of digits\n"
- " -f : Use %%f format, with a precision of digits\n"
- " -g : Use %%g format, with a precision of digits\n"
- " -s: Get value as string (honors server-side precision)\n"
- " -lx: Round to long integer and print as hex number\n"
- " -lo: Round to long integer and print as octal number\n"
- " -lb: Round to long integer and print as binary number\n"
+ " -n: Print DBF_ENUM values as number (default is enum string)\n"
+ "Array values: Print number of elements, then list of values\n"
+ " Default: Request and print all elements (dynamic arrays supported)\n"
+ " -# : Request and print up to elements\n"
+ " -S: Print arrays of char as a string (long string)\n"
+ "Floating point format:\n"
+ " Default: Use %%g format\n"
+ " -e : Use %%e format, with a precision of digits\n"
+ " -f : Use %%f format, with a precision of digits\n"
+ " -g : Use %%g format, with a precision of digits\n"
+ " -s: Get value as string (honors server-side precision)\n"
+ " -lx: Round to long integer and print as hex number\n"
+ " -lo: Round to long integer and print as octal number\n"
+ " -lb: Round to long integer and print as binary number\n"
"Integer number format:\n"
- " Default: Print as decimal number\n"
- " -0x: Print as hex number\n"
- " -0o: Print as octal number\n"
- " -0b: Print as binary number\n"
+ " Default: Print as decimal number\n"
+ " -0x: Print as hex number\n"
+ " -0o: Print as octal number\n"
+ " -0b: Print as binary number\n"
"Alternate output field separator:\n"
- " -F : Use as an alternate output field separator\n"
- "\nExample: camonitor -f8 my_channel another_channel\n"
+ " -F : Use to separate fields in output\n"
+ "\n"
+ "Example: camonitor -f8 my_channel another_channel\n"
" (doubles are printed as %%f with precision of 8)\n\n"
, DEFAULT_TIMEOUT, CA_PRIORITY_MAX);
}
@@ -92,7 +96,7 @@ void usage (void)
* Function: event_handler
*
* Description: CA event_handler for request type callback
- * Allocates the dbr structure and copies the data
+ * Prints the event data
*
* Arg(s) In: args - event handler args (see CA manual)
*
@@ -107,10 +111,12 @@ static void event_handler (evargs args)
{
pv->dbrType = args.type;
pv->nElems = args.count;
- memcpy(pv->value, args.dbr, dbr_size_n(args.type, args.count));
+ pv->value = (void *) args.dbr; /* casting away const */
print_time_val_sts(pv, reqElems);
fflush(stdout);
+
+ pv->value = NULL;
}
}
@@ -129,51 +135,39 @@ static void connection_handler ( struct connection_handler_args args )
{
pv *ppv = ( pv * ) ca_puser ( args.chid );
if ( args.op == CA_OP_CONN_UP ) {
+ nConn++;
+ if (!ppv->onceConnected) {
+ ppv->onceConnected = 1;
/* Set up pv structure */
/* ------------------- */
/* Get natural type and array count */
- ppv->nElems = ca_element_count(ppv->chid);
- ppv->dbfType = ca_field_type(ppv->chid);
+ ppv->dbfType = ca_field_type(ppv->chid);
+ ppv->dbrType = dbf_type_to_DBR_TIME(ppv->dbfType); /* Use native type */
+ if (dbr_type_is_ENUM(ppv->dbrType)) /* Enums honour -n option */
+ {
+ if (enumAsNr) ppv->dbrType = DBR_TIME_INT;
+ else ppv->dbrType = DBR_TIME_STRING;
+ }
+ else if (floatAsString &&
+ (dbr_type_is_FLOAT(ppv->dbrType) || dbr_type_is_DOUBLE(ppv->dbrType)))
+ {
+ ppv->dbrType = DBR_TIME_STRING;
+ }
+ /* Set request count */
+ ppv->nElems = ca_element_count(ppv->chid);
+ ppv->reqElems = reqElems > ppv->nElems ? ppv->nElems : reqElems;
- /* Set up value structures */
- ppv->dbrType = dbf_type_to_DBR_TIME(ppv->dbfType); /* Use native type */
- if (dbr_type_is_ENUM(ppv->dbrType)) /* Enums honour -n option */
- {
- if (enumAsNr) ppv->dbrType = DBR_TIME_INT;
- else ppv->dbrType = DBR_TIME_STRING;
- }
-
- else if (floatAsString &&
- (dbr_type_is_FLOAT(ppv->dbrType) || dbr_type_is_DOUBLE(ppv->dbrType)))
- {
- ppv->dbrType = DBR_TIME_STRING;
- }
- /* Adjust array count */
- if (reqElems > ppv->nElems)
- reqElems = ppv->nElems;
- ppv->reqElems = reqElems;
-
- ppv->onceConnected = 1;
- nConn++;
/* Issue CA request */
/* ---------------- */
- /* install monitor once with first connect */
- if ( ! ppv->value ) {
- /* Allocate value structure */
- ppv->value = calloc(1, dbr_size_n(ppv->dbrType, ppv->nElems));
- if ( ppv->value ) {
- ppv->status = ca_create_subscription(ppv->dbrType,
+ /* install monitor once with first connect */
+ ppv->status = ca_create_subscription(ppv->dbrType,
ppv->reqElems,
ppv->chid,
eventMask,
event_handler,
(void*)ppv,
NULL);
- if ( ppv->status != ECA_NORMAL ) {
- free ( ppv->value );
- }
- }
}
}
else if ( args.op == CA_OP_CONN_DOWN ) {
@@ -203,7 +197,7 @@ static void connection_handler ( struct connection_handler_args args )
int main (int argc, char *argv[])
{
int returncode = 0;
- int n = 0;
+ int n;
int result; /* CA result */
IntFormatT outType; /* Output type */
@@ -211,7 +205,7 @@ int main (int argc, char *argv[])
int digits = 0; /* getopt() no. of float digits */
int nPvs; /* Number of PVs */
- pv* pvs = 0; /* Array of PV structures */
+ pv* pvs; /* Array of PV structures */
LINE_BUFFER(stdout); /* Configure stdout buffering */
@@ -356,7 +350,7 @@ int main (int argc, char *argv[])
result = ca_context_create(ca_disable_preemptive_callback);
if (result != ECA_NORMAL) {
fprintf(stderr, "CA error %s occurred while trying "
- "to start channel access '%s'.\n", ca_message(result), pvs[n].name);
+ "to start channel access.\n", ca_message(result));
return 1;
}
/* Allocate PV structure array */
diff --git a/src/catools/caput.c b/src/catools/caput.c
index 9aaba38dc..cea443c0d 100644
--- a/src/catools/caput.c
+++ b/src/catools/caput.c
@@ -251,7 +251,6 @@ int caget (pv *pvs, int nPvs, OutputT format,
int main (int argc, char *argv[])
{
- int n = 0;
int i;
int result; /* CA result */
OutputT format = plain; /* User specified format */
@@ -273,7 +272,7 @@ int main (int argc, char *argv[])
struct dbr_gr_enum bufGrEnum;
int nPvs; /* Number of PVs */
- pv* pvs = 0; /* Array of PV structures */
+ pv* pvs; /* Array of PV structures */
LINE_BUFFER(stdout); /* Configure stdout buffering */
putenv("POSIXLY_CORRECT="); /* Behave correct on GNU getopt systems */
@@ -372,7 +371,7 @@ int main (int argc, char *argv[])
result = ca_context_create(ca_enable_preemptive_callback);
if (result != ECA_NORMAL) {
fprintf(stderr, "CA error %s occurred while trying "
- "to start channel access '%s'.\n", ca_message(result), pvs[n].name);
+ "to start channel access.\n", ca_message(result));
return 1;
}
/* Allocate PV structure array */
diff --git a/src/db/Makefile b/src/db/Makefile
index 7b8f82811..0ebdffdb6 100644
--- a/src/db/Makefile
+++ b/src/db/Makefile
@@ -33,8 +33,6 @@ INC += dbIocRegister.h
# The following go away what old database access goes away
INC += db_access_routines.h
INC += db_convert.h
-# The following is used by iocmon
-INC += dbCaPvt.h
DBDINC += menuAlarmSevr
DBDINC += menuAlarmStat
diff --git a/src/db/dbCAC.h b/src/db/dbCAC.h
index 363e82a2b..685d53a30 100644
--- a/src/db/dbCAC.h
+++ b/src/db/dbCAC.h
@@ -8,7 +8,7 @@
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
- * Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd
+ * Revision-Id: anj@aps.anl.gov-20110601222212-z1p7qoplm5mw0eho
*
*
* L O S A L A M O S
@@ -196,8 +196,8 @@ private:
dbContextReadNotifyCache readNotifyCache;
dbEventCtx ctx;
unsigned long stateNotifyCacheSize;
- mutable epicsMutex & mutex;
- mutable epicsMutex & cbMutex;
+ epicsMutex & mutex;
+ epicsMutex & cbMutex;
cacContextNotify & notify;
epics_auto_ptr < cacContext > pNetContext;
char * pStateNotifyCache;
diff --git a/src/db/dbCommon.dbd b/src/db/dbCommon.dbd
index 94128ca35..eb8e7bf35 100644
--- a/src/db/dbCommon.dbd
+++ b/src/db/dbCommon.dbd
@@ -43,11 +43,10 @@
special(SPC_SCAN)
interest(1)
}
- field(EVNT,DBF_STRING) {
- prompt("Event Name")
+ field(EVNT,DBF_SHORT) {
+ prompt("Event Number")
promptgroup(GUI_SCAN)
special(SPC_SCAN)
- size(40)
interest(1)
}
field(TSE,DBF_SHORT) {
diff --git a/src/db/dbEvent.c b/src/db/dbEvent.c
index 7dfb44b3c..e6079fda6 100644
--- a/src/db/dbEvent.c
+++ b/src/db/dbEvent.c
@@ -8,7 +8,7 @@
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* dbEvent.c */
-/* Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd */
+/* Revision-Id: johill@lanl.gov-20111019180700-7u25j7zwo2w1894n */
/* routines for scheduling events to lower priority tasks via the RT kernel */
/*
* Author: Jeffrey O. Hill
@@ -203,35 +203,44 @@ int epicsShareAPI dbel ( const char *pname, unsigned level )
}
if ( level > 1 ) {
- unsigned nEntriesFree = ringSpace ( pevent->ev_que );
+ unsigned nEntriesFree;
+ const void * taskId;
+ LOCKEVQUE(pevent->ev_que);
+ nEntriesFree = ringSpace ( pevent->ev_que );
+ taskId = ( void * ) pevent->ev_que->evUser->taskid;
+ UNLOCKEVQUE(pevent->ev_que);
if ( nEntriesFree == 0u ) {
printf ( ", thread=%p, queue full",
- (void *) pevent->ev_que->evUser->taskid );
+ (void *) taskId );
}
else if ( nEntriesFree == EVENTQUESIZE ) {
printf ( ", thread=%p, queue empty",
- (void *) pevent->ev_que->evUser->taskid );
+ (void *) taskId );
}
else {
printf ( ", thread=%p, unused entries=%u",
- (void *) pevent->ev_que->evUser->taskid, nEntriesFree );
+ (void *) taskId, nEntriesFree );
}
}
if ( level > 2 ) {
+ unsigned nDuplicates;
+ unsigned nCanceled;
if ( pevent->nreplace ) {
printf (", discarded by replacement=%ld", pevent->nreplace);
}
if ( ! pevent->valque ) {
printf (", queueing disabled" );
}
- if ( pevent->ev_que->nDuplicates ) {
- printf (", duplicate count =%u\n",
- pevent->ev_que->nDuplicates );
+ LOCKEVQUE(pevent->ev_que);
+ nDuplicates = pevent->ev_que->nDuplicates;
+ nCanceled = pevent->ev_que->nCanceled;
+ UNLOCKEVQUE(pevent->ev_que);
+ if ( nDuplicates ) {
+ printf (", duplicate count =%u\n", nDuplicates );
}
- if ( pevent->ev_que->nCanceled ) {
- printf (", canceled count =%u\n",
- pevent->ev_que->nCanceled );
+ if ( nCanceled ) {
+ printf (", canceled count =%u\n", nCanceled );
}
}
@@ -264,7 +273,7 @@ int epicsShareAPI dbel ( const char *pname, unsigned level )
*/
dbEventCtx epicsShareAPI db_init_events (void)
{
- struct event_user *evUser;
+ struct event_user * evUser;
if (!dbevEventUserFreeList) {
freeListInitPvt(&dbevEventUserFreeList,
@@ -326,7 +335,7 @@ dbEventCtx epicsShareAPI db_init_events (void)
*/
void epicsShareAPI db_close_events (dbEventCtx ctx)
{
- struct event_user *evUser = (struct event_user *) ctx;
+ struct event_user * const evUser = (struct event_user *) ctx;
/*
* Exit not forced on event blocks for now - this is left to channel
@@ -336,13 +345,32 @@ void epicsShareAPI db_close_events (dbEventCtx ctx)
* NOTE: not deleting events before calling this routine could be
* hazardous to the system's health.
*/
-
+ epicsMutexMustLock ( evUser->lock );
evUser->pendexit = TRUE;
-
+ epicsMutexUnlock ( evUser->lock );
/* notify the waiting task */
epicsEventSignal(evUser->ppendsem);
}
+/*
+ * create_ev_que()
+ */
+static struct event_que * create_ev_que ( struct event_user * const evUser )
+{
+ struct event_que * const ev_que = (struct event_que *)
+ freeListCalloc ( dbevEventQueueFreeList );
+ if ( ! ev_que ) {
+ return NULL;
+ }
+ ev_que->writelock = epicsMutexCreate();
+ if ( ! ev_que->writelock ) {
+ freeListFree ( dbevEventQueueFreeList, ev_que );
+ return NULL;
+ }
+ ev_que->evUser = evUser;
+ return ev_que;
+}
+
/*
* DB_ADD_EVENT()
*/
@@ -350,13 +378,9 @@ dbEventSubscription epicsShareAPI db_add_event (
dbEventCtx ctx, struct dbAddr *paddr,
EVENTFUNC *user_sub, void *user_arg, unsigned select)
{
- struct event_user *evUser = (struct event_user *) ctx;
- struct dbCommon *precord;
- struct event_que *ev_que;
- struct event_que *tmp_que;
- struct evSubscrip *pevent;
-
- precord = paddr->precord;
+ struct event_user * const evUser = (struct event_user *) ctx;
+ struct event_que * ev_que;
+ struct evSubscrip * pevent;
/*
* Don't add events which will not be triggered
@@ -365,38 +389,42 @@ dbEventSubscription epicsShareAPI db_add_event (
return NULL;
}
- pevent = freeListCalloc (dbevEventBlockFreeList);
- if (!pevent) {
+ pevent = freeListCalloc ( dbevEventBlockFreeList );
+ if ( ! pevent ) {
return NULL;
}
/* find an event que block with enough quota */
/* otherwise add a new one to the list */
- ev_que = &evUser->firstque;
- while (TRUE) {
- if (ev_que->quota + ev_que->nCanceled < EVENTQUESIZE - EVENTENTRIES) {
+ epicsMutexMustLock ( evUser->lock );
+ ev_que = & evUser->firstque;
+ while ( TRUE ) {
+ int success = 0;
+ LOCKEVQUE ( ev_que );
+ success = ( ev_que->quota + ev_que->nCanceled <
+ EVENTQUESIZE - EVENTENTRIES );
+ if ( success ) {
+ ev_que->quota += EVENTENTRIES;
+ }
+ UNLOCKEVQUE ( ev_que );
+ if ( success ) {
break;
}
- if (!ev_que->nextque) {
- tmp_que = (struct event_que *)
- freeListCalloc(dbevEventQueueFreeList);
- if (!tmp_que) {
- freeListFree (dbevEventBlockFreeList, pevent);
- return NULL;
+ if ( ! ev_que->nextque ) {
+ ev_que->nextque = create_ev_que ( evUser );
+ if ( ! ev_que->nextque ) {
+ ev_que = NULL;
+ break;
}
- tmp_que->evUser = evUser;
- tmp_que->writelock = epicsMutexCreate();
- if (!tmp_que->writelock) {
- freeListFree (dbevEventBlockFreeList, pevent);
- freeListFree (dbevEventQueueFreeList, tmp_que);
- return NULL;
- }
- ev_que->nextque = tmp_que;
- ev_que = tmp_que;
- break;
}
ev_que = ev_que->nextque;
}
+ epicsMutexUnlock ( evUser->lock );
+
+ if ( ! ev_que ) {
+ freeListFree ( dbevEventBlockFreeList, pevent );
+ return NULL;
+ }
pevent->npend = 0ul;
pevent->nreplace = 0ul;
@@ -409,10 +437,6 @@ dbEventSubscription epicsShareAPI db_add_event (
pevent->enabled = FALSE;
pevent->ev_que = ev_que;
- LOCKEVQUE(ev_que);
- ev_que->quota += EVENTENTRIES;
- UNLOCKEVQUE(ev_que);
-
/*
* Simple types values queued up for reliable interprocess
* communication (for other types they get whatever happens to be
@@ -434,10 +458,9 @@ dbEventSubscription epicsShareAPI db_add_event (
*/
void epicsShareAPI db_event_enable (dbEventSubscription es)
{
- struct evSubscrip *pevent = (struct evSubscrip *) es;
- struct dbCommon *precord;
-
- precord = (struct dbCommon *) pevent->paddr->precord;
+ struct evSubscrip * const pevent = (struct evSubscrip *) es;
+ struct dbCommon * const precord =
+ (struct dbCommon *) pevent->paddr->precord;
LOCKREC(precord);
if ( ! pevent->enabled ) {
@@ -452,10 +475,9 @@ void epicsShareAPI db_event_enable (dbEventSubscription es)
*/
void epicsShareAPI db_event_disable (dbEventSubscription es)
{
- struct evSubscrip *pevent = (struct evSubscrip *) es;
- struct dbCommon *precord;
-
- precord = (struct dbCommon *) pevent->paddr->precord;
+ struct evSubscrip * const pevent = (struct evSubscrip *) es;
+ struct dbCommon * const precord =
+ (struct dbCommon *) pevent->paddr->precord;
LOCKREC(precord);
if ( pevent->enabled ) {
@@ -472,7 +494,7 @@ void epicsShareAPI db_event_disable (dbEventSubscription es)
static void event_remove ( struct event_que *ev_que,
unsigned short index, struct evSubscrip *placeHolder )
{
- struct evSubscrip *pEvent = ev_que->evque[index];
+ struct evSubscrip * const pEvent = ev_que->evque[index];
ev_que->evque[index] = placeHolder;
if ( pEvent->npend == 1u ) {
@@ -495,12 +517,9 @@ static void event_remove ( struct event_que *ev_que,
*/
void epicsShareAPI db_cancel_event (dbEventSubscription es)
{
- struct evSubscrip * pevent = ( struct evSubscrip * ) es;
- struct dbCommon * precord;
+ struct evSubscrip * const pevent = ( struct evSubscrip * ) es;
unsigned short getix;
- precord = ( struct dbCommon * ) pevent->paddr->precord;
-
db_event_disable ( es );
/*
@@ -564,12 +583,12 @@ void epicsShareAPI db_cancel_event (dbEventSubscription es)
*/
void epicsShareAPI db_flush_extra_labor_event (dbEventCtx ctx)
{
- struct event_user *evUser = (struct event_user *) ctx;
+ struct event_user * const evUser = (struct event_user *) ctx;
epicsMutexMustLock ( evUser->lock );
while ( evUser->extraLaborBusy ) {
epicsMutexUnlock ( evUser->lock );
- epicsThreadSleep(1.0);
+ epicsThreadSleep(0.1);
epicsMutexMustLock ( evUser->lock );
}
epicsMutexUnlock ( evUser->lock );
@@ -585,7 +604,7 @@ void epicsShareAPI db_flush_extra_labor_event (dbEventCtx ctx)
int epicsShareAPI db_add_extra_labor_event (
dbEventCtx ctx, EXTRALABORFUNC *func, void *arg)
{
- struct event_user *evUser = (struct event_user *) ctx;
+ struct event_user * const evUser = (struct event_user *) ctx;
epicsMutexMustLock ( evUser->lock );
evUser->extralabor_sub = func;
@@ -600,7 +619,7 @@ int epicsShareAPI db_add_extra_labor_event (
*/
int epicsShareAPI db_post_extra_labor (dbEventCtx ctx)
{
- struct event_user *evUser = (struct event_user *) ctx;
+ struct event_user * const evUser = (struct event_user *) ctx;
int doit;
epicsMutexMustLock ( evUser->lock );
@@ -627,12 +646,10 @@ int epicsShareAPI db_post_extra_labor (dbEventCtx ctx)
*/
static void db_post_single_event_private (struct evSubscrip *event)
{
- struct event_que *ev_que;
- db_field_log *pLog;
- int firstEventFlag;
- unsigned rngSpace;
-
- ev_que = event->ev_que;
+ struct event_que * const ev_que = event->ev_que;
+ db_field_log * pLog;
+ int firstEventFlag;
+ unsigned rngSpace;
/*
* evUser ring buffer must be locked for the multiple
@@ -747,10 +764,10 @@ void *pField,
unsigned int caEventMask
)
{
- struct dbCommon *pdbc = (struct dbCommon *)pRecord;
- struct evSubscrip *event;
+ struct dbCommon * const pdbc = (struct dbCommon *)pRecord;
+ struct evSubscrip * event;
- if (pdbc->mlis.count == 0) return DB_EVENT_OK; /* no monitors set */
+ if (pdbc->mlis.count == 0) return DB_EVENT_OK; /* no monitors set */
LOCKREC(pdbc);
@@ -762,8 +779,7 @@ unsigned int caEventMask
* changed or pval==NULL and waiting on alarms and alarms changed
*/
if ( (event->paddr->pfield == (void *)pField || pField==NULL) &&
- (caEventMask & event->select)) {
-
+ (caEventMask & event->select) ) {
db_post_single_event_private (event);
}
}
@@ -778,8 +794,8 @@ unsigned int caEventMask
*/
void epicsShareAPI db_post_single_event (dbEventSubscription es)
{
- struct evSubscrip *event = (struct evSubscrip *) es;
- struct dbCommon *precord = event->paddr->precord;
+ struct evSubscrip * const event = (struct evSubscrip *) es;
+ struct dbCommon * const precord = event->paddr->precord;
dbScanLock (precord);
db_post_single_event_private (event);
@@ -898,8 +914,8 @@ static int event_read ( struct event_que *ev_que )
*/
static void event_task (void *pParm)
{
- struct event_user *evUser = (struct event_user *) pParm;
- struct event_que *ev_que;
+ struct event_user * const evUser = (struct event_user *) pParm;
+ struct event_que * ev_que;
/* init hook */
if (evUser->init_func) {
@@ -934,12 +950,14 @@ static void event_task (void *pParm)
epicsMutexMustLock ( evUser->lock );
}
evUser->extraLaborBusy = FALSE;
- epicsMutexUnlock ( evUser->lock );
for ( ev_que = &evUser->firstque; ev_que;
ev_que = ev_que->nextque ) {
+ epicsMutexUnlock ( evUser->lock );
event_read (ev_que);
+ epicsMutexMustLock ( evUser->lock );
}
+ epicsMutexUnlock ( evUser->lock );
} while( ! evUser->pendexit );
@@ -975,7 +993,7 @@ int epicsShareAPI db_start_events (
dbEventCtx ctx,const char *taskname, void (*init_func)(void *),
void *init_func_arg, unsigned osiPriority )
{
- struct event_user *evUser = (struct event_user *) ctx;
+ struct event_user * const evUser = (struct event_user *) ctx;
epicsMutexMustLock ( evUser->lock );
@@ -995,7 +1013,8 @@ int epicsShareAPI db_start_events (
taskname = EVENT_PEND_NAME;
}
evUser->taskid = epicsThreadCreate (
- taskname, osiPriority, epicsThreadGetStackSize(epicsThreadStackMedium),
+ taskname, osiPriority,
+ epicsThreadGetStackSize(epicsThreadStackMedium),
event_task, (void *)evUser);
if (!evUser->taskid) {
epicsMutexUnlock ( evUser->lock );
@@ -1008,9 +1027,10 @@ int epicsShareAPI db_start_events (
/*
* db_event_change_priority()
*/
-void epicsShareAPI db_event_change_priority ( dbEventCtx ctx, unsigned epicsPriority )
+void epicsShareAPI db_event_change_priority ( dbEventCtx ctx,
+ unsigned epicsPriority )
{
- struct event_user * evUser = ( struct event_user * ) ctx;
+ struct event_user * const evUser = ( struct event_user * ) ctx;
epicsThreadSetPriority ( evUser->taskid, epicsPriority );
}
@@ -1019,9 +1039,11 @@ void epicsShareAPI db_event_change_priority ( dbEventCtx ctx, unsigned epicsPrio
*/
void epicsShareAPI db_event_flow_ctrl_mode_on (dbEventCtx ctx)
{
- struct event_user *evUser = (struct event_user *) ctx;
+ struct event_user * const evUser = (struct event_user *) ctx;
+ epicsMutexMustLock ( evUser->lock );
evUser->flowCtrlMode = TRUE;
+ epicsMutexUnlock ( evUser->lock );
/*
* notify the event handler task
*/
@@ -1036,9 +1058,11 @@ void epicsShareAPI db_event_flow_ctrl_mode_on (dbEventCtx ctx)
*/
void epicsShareAPI db_event_flow_ctrl_mode_off (dbEventCtx ctx)
{
- struct event_user *evUser = (struct event_user *) ctx;
+ struct event_user * const evUser = (struct event_user *) ctx;
+ epicsMutexMustLock ( evUser->lock );
evUser->flowCtrlMode = FALSE;
+ epicsMutexUnlock ( evUser->lock );
/*
* notify the event handler task
*/
diff --git a/src/db/dbIocRegister.c b/src/db/dbIocRegister.c
index c64738bbd..a82337f03 100644
--- a/src/db/dbIocRegister.c
+++ b/src/db/dbIocRegister.c
@@ -266,11 +266,11 @@ static void scanpplCallFunc(const iocshArgBuf *args)
{ scanppl(args[0].dval);}
/* scanpel */
-static const iocshArg scanpelArg0 = { "event name",iocshArgString};
+static const iocshArg scanpelArg0 = { "event number",iocshArgInt};
static const iocshArg * const scanpelArgs[1] = {&scanpelArg0};
static const iocshFuncDef scanpelFuncDef = {"scanpel",1,scanpelArgs};
static void scanpelCallFunc(const iocshArgBuf *args)
-{ scanpel(args[0].sval);}
+{ scanpel(args[0].ival);}
/* scanpiol */
static const iocshFuncDef scanpiolFuncDef = {"scanpiol",0};
diff --git a/src/db/dbPutNotifyBlocker.cpp b/src/db/dbPutNotifyBlocker.cpp
index 5dbee30bf..92f6d06e7 100644
--- a/src/db/dbPutNotifyBlocker.cpp
+++ b/src/db/dbPutNotifyBlocker.cpp
@@ -9,7 +9,7 @@
\*************************************************************************/
/*
- * Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd
+ * Revision-Id: johill@lanl.gov-20111019180700-7u25j7zwo2w1894n
*
*
* L O S A L A M O S
@@ -74,7 +74,7 @@ void dbPutNotifyBlocker::cancel (
epicsGuard < epicsMutex > & guard )
{
guard.assertIdenticalMutex ( this->mutex );
- if ( this->pn.paddr ) {
+ if ( this->pNotify ) {
epicsGuardRelease < epicsMutex > unguard ( guard );
dbNotifyCancel ( &this->pn );
}
@@ -100,26 +100,31 @@ void dbPutNotifyBlocker::expandValueBuf (
extern "C" void putNotifyCompletion ( putNotify *ppn )
{
- dbPutNotifyBlocker * pBlocker = static_cast < dbPutNotifyBlocker * > ( ppn->usrPvt );
- {
- epicsGuard < epicsMutex > guard ( pBlocker->mutex );
- if ( pBlocker->pNotify ) {
- if ( pBlocker->pn.status != putNotifyOK) {
- pBlocker->pNotify->exception (
- guard, ECA_PUTFAIL, "put notify unsuccessful",
- static_cast (pBlocker->pn.dbrType),
- static_cast (pBlocker->pn.nRequest) );
- }
- else {
- pBlocker->pNotify->completion ( guard );
- }
+ dbPutNotifyBlocker * const pBlocker =
+ static_cast < dbPutNotifyBlocker * > ( ppn->usrPvt );
+ epicsGuard < epicsMutex > guard ( pBlocker->mutex );
+ cacWriteNotify * const pNtfy = pBlocker->pNotify;
+ if ( pNtfy ) {
+ pBlocker->pNotify = 0;
+ // Its necessary to signal the initiators now before we call
+ // the user callback. This is less efficent, and potentially
+ // causes more thread context switching, but its probably
+ // unavoidable because its possible that the use callback
+ // might destroy this object.
+ pBlocker->block.signal ();
+ if ( pBlocker->pn.status != putNotifyOK ) {
+ pNtfy->exception (
+ guard, ECA_PUTFAIL, "put notify unsuccessful",
+ static_cast < unsigned > (pBlocker->pn.dbrType),
+ static_cast < unsigned > (pBlocker->pn.nRequest) );
}
else {
- errlogPrintf ( "put notify completion with nill pNotify?\n" );
+ pNtfy->completion ( guard );
}
- pBlocker->pNotify = 0;
}
- pBlocker->block.signal ();
+ else {
+ errlogPrintf ( "put notify completion with nill pNotify?\n" );
+ }
}
void dbPutNotifyBlocker::initiatePutNotify (
diff --git a/src/db/dbScan.c b/src/db/dbScan.c
index 1720a5d85..5a372d6a9 100644
--- a/src/db/dbScan.c
+++ b/src/db/dbScan.c
@@ -101,13 +101,12 @@ static char *priorityName[NUM_CALLBACK_PRIORITIES] = {
/* EVENT */
-typedef struct event_list {
- CALLBACK callback[NUM_CALLBACK_PRIORITIES];
- scan_list scan_list[NUM_CALLBACK_PRIORITIES];
- struct event_list *next;
- char event_name[MAX_STRING_SIZE];
-} event_list;
-static event_list * volatile pevent_list[256];
+#define MAX_EVENTS 256
+typedef struct event_scan_list {
+ CALLBACK callback;
+ scan_list scan_list;
+} event_scan_list;
+static event_scan_list *pevent_list[NUM_CALLBACK_PRIORITIES][MAX_EVENTS];
/* IO_EVENT*/
@@ -205,24 +204,35 @@ void scanAdd(struct dbCommon *precord)
recGblRecordError(-1, (void *)precord,
"scanAdd detected illegal SCAN value");
} else if (scan == menuScanEvent) {
- char* eventname;
+ int evnt;
int prio;
- event_list *pel;
+ event_scan_list *pesl;
- eventname = precord->evnt;
- if (strlen(eventname) >= MAX_STRING_SIZE) {
+ evnt = precord->evnt;
+ if (evnt < 0 || evnt >= MAX_EVENTS) {
recGblRecordError(S_db_badField, (void *)precord,
- "scanAdd: too long EVNT value");
+ "scanAdd detected illegal EVNT value");
+ precord->scan = menuScanPassive;
return;
}
prio = precord->prio;
if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
recGblRecordError(-1, (void *)precord,
"scanAdd: illegal prio field");
+ precord->scan = menuScanPassive;
return;
}
- pel = eventNameToHandle(eventname);
- if (pel) addToList(precord, &pel->scan_list[prio]);
+ pesl = pevent_list[prio][evnt];
+ if (pesl == NULL) {
+ pesl = dbCalloc(1, sizeof(event_scan_list));
+ pevent_list[prio][evnt] = pesl;
+ pesl->scan_list.lock = epicsMutexMustCreate();
+ callbackSetCallback(eventCallback, &pesl->callback);
+ callbackSetPriority(prio, &pesl->callback);
+ callbackSetUser(pesl, &pesl->callback);
+ ellInit(&pesl->scan_list.list);
+ }
+ addToList(precord, &pesl->scan_list);
} else if (scan == menuScanI_O_Intr) {
io_scan_list *piosl = NULL;
int prio;
@@ -277,25 +287,31 @@ void scanDelete(struct dbCommon *precord)
recGblRecordError(-1, (void *)precord,
"scanDelete detected illegal SCAN value");
} else if (scan == menuScanEvent) {
- char* eventname;
+ int evnt;
int prio;
- event_list *pel;
+ event_scan_list *pesl;
scan_list *psl = 0;
- eventname = precord->evnt;
+ evnt = precord->evnt;
+ if (evnt < 0 || evnt >= MAX_EVENTS) {
+ recGblRecordError(S_db_badField, (void *)precord,
+ "scanAdd detected illegal EVNT value");
+ precord->scan = menuScanPassive;
+ return;
+ }
prio = precord->prio;
if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
recGblRecordError(-1, (void *)precord,
- "scanDelete detected illegal PRIO field");
+ "scanAdd: illegal prio field");
+ precord->scan = menuScanPassive;
return;
}
- do /* multithreading: make sure pel is consistent */
- pel = pevent_list[0];
- while (pel != pevent_list[0]);
- for (; pel; pel=pel->next) {
- if (strcmp(pel->event_name, eventname) == 0) break;
- }
- if (pel && (psl = &pel->scan_list[prio]))
+ pesl = pevent_list[prio][evnt];
+ if (pesl) psl = &pesl->scan_list;
+ if (!pesl || !psl)
+ recGblRecordError(-1, (void *)precord,
+ "scanDelete for bad evnt");
+ else
deleteFromList(precord, psl);
} else if (scan == menuScanI_O_Intr) {
io_scan_list *piosl=NULL;
@@ -356,22 +372,21 @@ int scanppl(double period) /* print periodic list */
return 0;
}
-int scanpel(char* eventname) /* print event list */
+int scanpel(int event_number) /* print event list */
{
char message[80];
- int prio;
- event_list *pel;
-
- do /* multithreading: make sure pel is consistent */
- pel = pevent_list[0];
- while (pel != pevent_list[0]);
- for (; pel; pel = pel->next) {
- if (!eventname || strcmp(pel->event_name, eventname) == 0) {
- for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
- if (ellCount(&pel->scan_list[prio].list) == 0) continue;
- sprintf(message, "Event \"%s\" Priority %s", pel->event_name, priorityName[prio]);
- printList(&pel->scan_list[prio], message);
- }
+ int prio, evnt;
+ event_scan_list *pesl;
+
+ for (evnt = 0; evnt < MAX_EVENTS; evnt++) {
+ if (event_number && evntevent_number) break;
+ for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
+ pesl = pevent_list[prio][evnt];
+ if (!pesl) continue;
+ if (ellCount(&pesl->scan_list.list) == 0) continue;
+ sprintf(message, "Event %d Priority %s", evnt, priorityName[prio]);
+ printList(&pesl->scan_list, message);
}
}
return 0;
@@ -397,73 +412,39 @@ int scanpiol(void) /* print io_event list */
static void eventCallback(CALLBACK *pcallback)
{
- scan_list *psl;
+ event_scan_list *pesl;
- callbackGetUser(psl, pcallback);
- scanList(psl);
+ callbackGetUser(pesl, pcallback);
+ scanList(&pesl->scan_list);
}
static void initEvent(void)
{
-}
+ int evnt, prio;
-event_list *eventNameToHandle(char *eventname)
-{
- int prio;
- event_list *pel;
- static epicsMutexId lock = NULL;
-
- if (!lock) lock = epicsMutexMustCreate();
- if (!eventname || eventname[0] == 0) return NULL;
- epicsMutexMustLock(lock);
- for (pel = pevent_list[0]; pel; pel=pel->next) {
- if (strcmp(pel->event_name, eventname) == 0) break;
- }
- if (pel == NULL) {
- pel = dbCalloc(1, sizeof(event_list));
- strcpy(pel->event_name, eventname);
- for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
- callbackSetUser(&pel->scan_list[prio], &pel->callback[prio]);
- callbackSetPriority(prio, &pel->callback[prio]);
- callbackSetCallback(eventCallback, &pel->callback[prio]);
- pel->scan_list[prio].lock = epicsMutexMustCreate();
- ellInit(&pel->scan_list[prio].list);
- }
- pel->next=pevent_list[0];
- pevent_list[0]=pel;
- { /* backward compatibility */
- char* p;
- long e = strtol(eventname, &p, 0);
- if (*p == 0 && e > 0 && e <= 255)
- pevent_list[e]=pel;
- }
- }
- epicsMutexUnlock(lock);
- return pel;
-}
-
-void postEvent(event_list *pel)
-{
- int prio;
-
- if (scanCtl != ctlRun) return;
- if (!pel) return;
for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
- if (ellCount(&pel->scan_list[prio].list) >0)
- callbackRequest(&pel->callback[prio]);
+ for (evnt = 0; evnt < MAX_EVENTS; evnt++) {
+ pevent_list[prio][evnt] = NULL;
+ }
}
}
-/* backward compatibility */
void post_event(int event)
{
- event_list* pel;
-
- if (event <= 0 || event > 255) return;
- do { /* multithreading: make sure pel is consistent */
- pel = pevent_list[event];
- } while (pel != pevent_list[event]);
- postEvent(pel);
+ int prio;
+ event_scan_list *pesl;
+
+ if (scanCtl != ctlRun) return;
+ if (event < 0 || event >= MAX_EVENTS) {
+ errMessage(-1, "illegal event passed to post_event");
+ return;
+ }
+ for (prio=0; prioscan_list.list) >0)
+ callbackRequest((void *)pesl);
+ }
}
void scanIoInit(IOSCANPVT *ppioscanpvt)
diff --git a/src/db/dbScan.h b/src/db/dbScan.h
index 1546bc9d2..e046235ca 100644
--- a/src/db/dbScan.h
+++ b/src/db/dbScan.h
@@ -19,7 +19,6 @@
#include "menuScan.h"
#include "shareLib.h"
-#include "compilerDependencies.h"
#ifdef __cplusplus
extern "C" {
@@ -33,13 +32,10 @@ extern "C" {
#define MAX_PHASE SHRT_MAX
#define MIN_PHASE SHRT_MIN
-#define HAVE_NAMED_SOFT_EVENTS
-
/*definitions for I/O Interrupt Scanning */
struct io_scan_list;
typedef struct io_scan_list *IOSCANPVT;
-typedef struct event_list *EVENTPVT;
struct dbCommon;
@@ -47,9 +43,7 @@ epicsShareFunc long scanInit(void);
epicsShareFunc void scanRun(void);
epicsShareFunc void scanPause(void);
-epicsShareFunc EVENTPVT eventNameToHandle(char* event);
-epicsShareFunc void postEvent(EVENTPVT epvt);
-epicsShareFunc void post_event(int event) EPICS_DEPRECATED;
+epicsShareFunc void post_event(int event);
epicsShareFunc void scanAdd(struct dbCommon *);
epicsShareFunc void scanDelete(struct dbCommon *);
epicsShareFunc double scanPeriod(int scan);
@@ -60,7 +54,7 @@ epicsShareFunc int scanOnceSetQueueSize(int size);
epicsShareFunc int scanppl(double rate);
/*print event lists*/
-epicsShareFunc int scanpel(char *event_name);
+epicsShareFunc int scanpel(int event_number);
/*print io_event list*/
epicsShareFunc int scanpiol(void);
diff --git a/src/dbStatic/dbExpand.c b/src/dbStatic/dbExpand.c
index 80c95cabd..5fac686d3 100644
--- a/src/dbStatic/dbExpand.c
+++ b/src/dbStatic/dbExpand.c
@@ -1,14 +1,13 @@
/*************************************************************************\
-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
+* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
-* EPICS BASE Versions 3.13.7
-* and higher are distributed subject to a Software License Agreement found
+* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* dbExpand.c */
-/* Author: Marty Kraimer Date: 30NOV95 */
+/* Author: Marty Kraimer Date: 30NOV95 */
#include
#include
@@ -25,24 +24,25 @@
#include "osiFileName.h"
DBBASE *pdbbase = NULL;
-
+
void usage(void)
{
- fprintf(stderr, "Usage:\n\tdbExpand -Ipath -ooutfile "
- "-S macro=value file1.dbd file2.dbd ...\n");
+ fprintf(stderr, "Usage:\n\tdbExpand -b -Ipath -ooutfile "
+ "-S macro=value file1.dbd file2.dbd ...\n");
fprintf(stderr,"Specifying any path will replace the default of '.'\n");
+ fprintf(stderr,"The -b option enables relaxed breakpoint table checking\n");
}
int main(int argc,char **argv)
{
- char *path = NULL;
- char *sub = NULL;
- int pathLength = 0;
- int subLength = 0;
+ char *path = NULL;
+ char *sub = NULL;
+ int pathLength = 0;
+ int subLength = 0;
char *outFilename = NULL;
FILE *outFP = stdout;
- long status;
- long returnStatus = 0;
+ long status;
+ long returnStatus = 0;
static char *pathSep = OSI_PATH_LIST_SEPARATOR;
static char *subSep = ",";
@@ -53,8 +53,8 @@ int main(int argc,char **argv)
while ((argc > 1) && (**argv == '-')) {
char optLtr = (*argv)[1];
char *optArg;
-
- if (strlen(*argv) > 2) {
+
+ if (strlen(*argv) > 2 || optLtr == 'b') {
optArg = *argv+2;
++argv;
--argc;
@@ -63,36 +63,40 @@ int main(int argc,char **argv)
argv += 2;
argc -= 2;
}
-
+
switch (optLtr) {
case 'o':
outFilename = optArg;
break;
-
+
case 'I':
dbCatString(&path, &pathLength, optArg, pathSep);
break;
-
+
case 'S':
dbCatString(&sub, &subLength, optArg, subSep);
break;
-
+
+ case 'b':
+ dbBptNotMonotonic = 1;
+ break;
+
default:
fprintf(stderr, "dbExpand: Unknown option '-%c'\n", optLtr);
usage();
exit(1);
}
}
-
+
if (argc < 1) {
- fprintf(stderr, "dbExpand: No input file specified\n");
+ fprintf(stderr, "dbExpand: No input file specified\n");
usage();
- exit(1);
+ exit(1);
}
-
+
for (; argc>0; --argc, ++argv) {
- status = dbReadDatabase(&pdbbase,*argv,path,sub);
- if (status) returnStatus = status;
+ status = dbReadDatabase(&pdbbase,*argv,path,sub);
+ if (status) returnStatus = status;
}
if (returnStatus) {
errlogFlush();
@@ -106,7 +110,7 @@ int main(int argc,char **argv)
exit(1);
}
}
-
+
dbWriteMenuFP(pdbbase,outFP,0);
dbWriteRecordTypeFP(pdbbase,outFP,0);
dbWriteDeviceFP(pdbbase,outFP);
@@ -116,7 +120,7 @@ int main(int argc,char **argv)
dbWriteVariableFP(pdbbase,outFP);
dbWriteBreaktableFP(pdbbase,outFP);
dbWriteRecordFP(pdbbase,outFP,0,0);
-
+
free((void *)path);
free((void *)sub);
return 0;
diff --git a/src/dbStatic/dbStaticLib.c b/src/dbStatic/dbStaticLib.c
index 3c53d1f63..b74e7c24a 100644
--- a/src/dbStatic/dbStaticLib.c
+++ b/src/dbStatic/dbStaticLib.c
@@ -6,7 +6,7 @@
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
-/* Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd */
+/* Revision-Id: anj@aps.anl.gov-20111129221419-re5dzg24xgranr6t */
#include
#include
@@ -3916,7 +3916,7 @@ void epicsShareAPI dbDumpField(
else
printf("\t field_type: %s\n", pamapdbfType[j].strvalue);
printf("\tprocess_passive: %hd\n",pdbFldDes->process_passive);
- printf("\t base: %hd\n",pdbFldDes->base);
+ printf("\t base: %d\n",pdbFldDes->base);
if(!pdbFldDes->promptgroup) {
printf("\t promptgroup: %d\n",pdbFldDes->promptgroup);
} else {
@@ -3929,7 +3929,7 @@ void epicsShareAPI dbDumpField(
}
}
printf("\t interest: %hd\n", pdbFldDes->interest);
- printf("\t as_level: %hd\n",pdbFldDes->as_level);
+ printf("\t as_level: %d\n",pdbFldDes->as_level);
printf("\t initial: %s\n",
(pdbFldDes->initial ? pdbFldDes->initial : ""));
if(pdbFldDes->field_type==DBF_MENU) {
diff --git a/src/dbStatic/dbStaticLib.h b/src/dbStatic/dbStaticLib.h
index 9a406784a..c0934aa3b 100644
--- a/src/dbStatic/dbStaticLib.h
+++ b/src/dbStatic/dbStaticLib.h
@@ -6,7 +6,7 @@
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
-/* Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd
+/* Revision-Id: anj@aps.anl.gov-20111128185555-mu76mhfkfutzrdca
*
* Author: Marty Kraimer
* Date: 06-08-93
@@ -74,6 +74,8 @@ epicsShareFunc DBENTRY * epicsShareAPI dbCopyEntry(DBENTRY *pdbentry);
epicsShareFunc void epicsShareAPI dbCopyEntryContents(DBENTRY *pfrom,
DBENTRY *pto);
+epicsShareExtern int dbBptNotMonotonic;
+
epicsShareFunc long epicsShareAPI dbReadDatabase(DBBASE **ppdbbase,
const char *filename, const char *path, const char *substitutions);
epicsShareFunc long epicsShareAPI dbReadDatabaseFP(DBBASE **ppdbbase,
diff --git a/src/dev/softDev/devEventSoft.c b/src/dev/softDev/devEventSoft.c
index d7a61172a..e276e0b82 100644
--- a/src/dev/softDev/devEventSoft.c
+++ b/src/dev/softDev/devEventSoft.c
@@ -51,7 +51,7 @@ static long init_record(eventRecord *prec)
/* INP must be CONSTANT, PV_LINK, DB_LINK or CA_LINK*/
switch (prec->inp.type) {
case CONSTANT:
- if (recGblInitConstantLink(&prec->inp, DBF_STRING, &prec->val))
+ if (recGblInitConstantLink(&prec->inp, DBF_USHORT, &prec->val))
prec->udf = FALSE;
break;
case PV_LINK:
@@ -69,20 +69,13 @@ static long init_record(eventRecord *prec)
static long read_event(eventRecord *prec)
{
long status;
- char newEvent[MAX_STRING_SIZE];
- if (prec->inp.type != CONSTANT)
- {
- status = dbGetLinkValue(&prec->inp, DBR_STRING, newEvent, 0, 0);
- if (status) return status;
- if (strcmp(newEvent, prec->val) != 0) {
- strcpy(prec->val, newEvent);
- prec->epvt = eventNameToHandle(prec->val);
- }
+ status = dbGetLink(&prec->inp, DBR_USHORT, &prec->val, 0, 0);
+ if (!status) {
+ prec->udf = FALSE;
+ if (prec->tsel.type == CONSTANT &&
+ prec->tse == epicsTimeEventDeviceTime)
+ dbGetTimeStamp(&prec->inp, &prec->time);
}
- prec->udf = FALSE;
- if (prec->tsel.type == CONSTANT &&
- prec->tse == epicsTimeEventDeviceTime)
- dbGetTimeStamp(&prec->inp, &prec->time);
- return 0;
+ return status;
}
diff --git a/src/excas/Makefile b/src/excas/Makefile
index 0d4d51638..aed68cd74 100644
--- a/src/excas/Makefile
+++ b/src/excas/Makefile
@@ -1,5 +1,5 @@
#*************************************************************************
-# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
+# Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
@@ -19,7 +19,7 @@ SRC_DIRS += $(TOP)/src/makeBaseApp/top/caServerApp
#
# Added ws2_32 winmm user32 for the non-dll build
#
-SYS_PROD_LIBS_WIN32 += ws2_32 advapi32 user32
+PROD_SYS_LIBS_WIN32 += ws2_32 advapi32 user32
PROD_HOST = excas
diff --git a/src/gdd/gdd.cc b/src/gdd/gdd.cc
index 8c9e90783..b422fd6b7 100644
--- a/src/gdd/gdd.cc
+++ b/src/gdd/gdd.cc
@@ -10,7 +10,7 @@
// Author: Jim Kowalkowski
// Date: 2/96
//
-// Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd
+// Revision-Id: anj@aps.anl.gov-20111129221419-re5dzg24xgranr6t
//
#include
@@ -1109,7 +1109,7 @@ gddStatus gdd::clearData(void)
str->clear();
}
else if ( this->primitiveType() == aitEnumFixedString ) {
- memset ( this->data.FString, '\0', sizeof ( this->data.FString ) );
+ memset ( this->data.FString, '\0', sizeof(aitFixedString) );
}
else {
memset ( & this->data, '\0', sizeof ( this->data ) );
diff --git a/src/libCom/Makefile b/src/libCom/Makefile
index 7f0168fb0..e14808371 100644
--- a/src/libCom/Makefile
+++ b/src/libCom/Makefile
@@ -222,8 +222,6 @@ SRCS += epicsTempFile.cpp
SRCS += epicsStdio.c
SRCS += osdStdio.c
-osdEnv_CFLAGS_WIN32= -U__STDC__
-
SRCS += osdThread.c
SRCS += osdMutex.c
SRCS += osdEvent.c
diff --git a/src/libCom/calc/postfix.c b/src/libCom/calc/postfix.c
index 79deeef8d..1f1a60789 100644
--- a/src/libCom/calc/postfix.c
+++ b/src/libCom/calc/postfix.c
@@ -405,12 +405,10 @@ epicsShareFunc long
pstacktop--;
}
-/*
- * if (cond_count != 0) {
- * *perror = CALC_ERR_CONDITIONAL;
- * goto bad;
- * }
- */
+ if (cond_count != 0) {
+ *perror = CALC_ERR_CONDITIONAL;
+ goto bad;
+ }
if (runtime_depth > 1) {
*perror = CALC_ERR_TOOMANY;
goto bad;
@@ -454,12 +452,10 @@ epicsShareFunc long
}
*pout = END_EXPRESSION;
-/*
- * if (cond_count != 0) {
- * *perror = CALC_ERR_CONDITIONAL;
- * goto bad;
- * }
- */
+ if (cond_count != 0) {
+ *perror = CALC_ERR_CONDITIONAL;
+ goto bad;
+ }
if (operand_needed || runtime_depth != 1) {
*perror = CALC_ERR_INCOMPLETE;
goto bad;
diff --git a/src/libCom/cxxTemplates/epicsSingleton.h b/src/libCom/cxxTemplates/epicsSingleton.h
index c522b820e..25e503723 100644
--- a/src/libCom/cxxTemplates/epicsSingleton.h
+++ b/src/libCom/cxxTemplates/epicsSingleton.h
@@ -9,7 +9,7 @@
\*************************************************************************/
/*
- * Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd
+ * Revision-Id: ralph.lange@gmx.de-20110808163119-szktwmb8pwbw5cec
*
* Author: Jeffrey O. Hill
*
@@ -34,7 +34,7 @@ public:
void * pInstance () const;
private:
void * _pInstance;
- size_t _refCount;
+ std :: size_t _refCount;
SingletonUntyped ( const SingletonUntyped & );
SingletonUntyped & operator = ( const SingletonUntyped & );
};
diff --git a/src/libCom/ellLib/ellLib.c b/src/libCom/ellLib/ellLib.c
index 1a59e8f30..c570f59d5 100644
--- a/src/libCom/ellLib/ellLib.c
+++ b/src/libCom/ellLib/ellLib.c
@@ -282,13 +282,6 @@ void ellFree2 (ELLLIST *pList, FREEFUNC freeFunc)
pList->count = 0;
}
-/* for backward compatibility provide a function ellFree() in addition to macro */
-#undef ellFree
-void ellFree (ELLLIST *pList)
-{
- ellFree2 (pList, free);
-}
-
/****************************************************************************
*
* This function verifies that the list is consistent.
diff --git a/src/libCom/error/errlog.c b/src/libCom/error/errlog.c
index 1cf1575bf..c5834057b 100644
--- a/src/libCom/error/errlog.c
+++ b/src/libCom/error/errlog.c
@@ -41,7 +41,6 @@
/*Declare storage for errVerbose */
epicsShareDef int errVerbose = 0;
-static void errlogCleanup(void);
static void exitHandler(void *);
static void errlogThread(void);
@@ -391,8 +390,15 @@ static void exitHandler(void *pvt)
pvtData.atExit = 1;
epicsEventSignal(pvtData.waitForWork);
epicsEventMustWait(pvtData.waitForExit);
+
+ free(pvtData.pbuffer);
+ epicsMutexDestroy(pvtData.flushLock);
+ epicsEventDestroy(pvtData.flush);
+ epicsEventDestroy(pvtData.waitForFlush);
+ epicsMutexDestroy(pvtData.listenerLock);
+ epicsMutexDestroy(pvtData.msgQueueLock);
+ epicsEventDestroy(pvtData.waitForWork);
epicsEventDestroy(pvtData.waitForExit);
- return;
}
struct initArgs {
@@ -432,18 +438,6 @@ static void errlogInitPvt(void *arg)
pvtData.errlogInitFailed = FALSE;
}
}
-
-static void errlogCleanup(void)
-{
- free(pvtData.pbuffer);
- epicsMutexDestroy(pvtData.flushLock);
- epicsEventDestroy(pvtData.flush);
- epicsEventDestroy(pvtData.waitForFlush);
- epicsMutexDestroy(pvtData.listenerLock);
- epicsMutexDestroy(pvtData.msgQueueLock);
- epicsEventDestroy(pvtData.waitForWork);
- /*Note that exitHandler must destroy waitForExit*/
-}
epicsShareFunc int epicsShareAPI errlogInit2(int bufsize, int maxMsgSize)
{
@@ -514,7 +508,6 @@ static void errlogThread(void)
epicsThreadSleep(.2); /*just wait an extra .2 seconds*/
epicsEventSignal(pvtData.waitForFlush);
}
- errlogCleanup();
epicsEventSignal(pvtData.waitForExit);
}
diff --git a/src/libCom/osi/os/Darwin/osdSock.h b/src/libCom/osi/os/Darwin/osdSock.h
index fc281c3d5..aed4c113d 100644
--- a/src/libCom/osi/os/Darwin/osdSock.h
+++ b/src/libCom/osi/os/Darwin/osdSock.h
@@ -1,11 +1,10 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Saskatchewan
-* EPICS BASE Versions 3.13.7
-* and higher are distributed subject to a Software License Agreement found
+* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
- * Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd
+ * Revision-Id: anj@aps.anl.gov-20110909221435-fdjubbxunee9gs44
*
* Author: Eric Norum
*/
@@ -13,10 +12,6 @@
#ifndef osdSockH
#define osdSockH
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include
#include
@@ -24,8 +19,6 @@ extern "C" {
#include
#include
#include
-/*#include
-#include */
#include
#include
#include
@@ -34,10 +27,6 @@ extern "C" {
#include /* close() and others */
-#ifdef __cplusplus
-}
-#endif
-
typedef int SOCKET;
#define INVALID_SOCKET (-1)
#define SOCKERRNO errno
diff --git a/src/libCom/osi/os/Linux/osdSock.h b/src/libCom/osi/os/Linux/osdSock.h
index 8c1f65b70..e689526eb 100644
--- a/src/libCom/osi/os/Linux/osdSock.h
+++ b/src/libCom/osi/os/Linux/osdSock.h
@@ -3,8 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
-* EPICS BASE Versions 3.13.7
-* and higher are distributed subject to a Software License Agreement found
+* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
@@ -26,10 +25,6 @@
#ifndef osdSockH
#define osdSockH
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include
#include
@@ -37,8 +32,6 @@ extern "C" {
#include
#include
#include
-/*#include
-#include */
#include
#include
#include
@@ -47,10 +40,6 @@ extern "C" {
#include /* close() and others */
-#ifdef __cplusplus
-}
-#endif
-
typedef int SOCKET;
#define INVALID_SOCKET (-1)
#define SOCKERRNO errno
diff --git a/src/libCom/osi/os/RTEMS/osdSock.h b/src/libCom/osi/os/RTEMS/osdSock.h
index 17125ff62..d5ba570bd 100644
--- a/src/libCom/osi/os/RTEMS/osdSock.h
+++ b/src/libCom/osi/os/RTEMS/osdSock.h
@@ -1,12 +1,11 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Saskatchewan
-* EPICS BASE Versions 3.13.7
-* and higher are distributed subject to a Software License Agreement found
+* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* RTEMS osdSock.h
- * Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd
+ * Revision-Id: anj@aps.anl.gov-20110909221435-fdjubbxunee9gs44
* Author: W. Eric Norum
* eric@cls.usask.ca
* (306) 966-6055
@@ -14,10 +13,6 @@
#ifndef osdSockH
#define osdSockH
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include
#include
@@ -32,6 +27,10 @@ extern "C" {
#include
#include
+#ifdef __cplusplus
+extern "C" {
+#endif
+
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
#ifdef __cplusplus
diff --git a/src/libCom/osi/os/RTEMS/osdTime.cpp b/src/libCom/osi/os/RTEMS/osdTime.cpp
index e7a419d60..bca82211b 100644
--- a/src/libCom/osi/os/RTEMS/osdTime.cpp
+++ b/src/libCom/osi/os/RTEMS/osdTime.cpp
@@ -6,7 +6,7 @@
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
- * Revision-Id: ralph.lange@bessy.de-20101020143551-76qdww31y8v01l24
+ * Revision-Id: anj@aps.anl.gov-20110823182000-bubidbqy4olqqdvq
*
* Author: W. Eric Norum
*/
@@ -18,6 +18,7 @@
#include
#include
#include
+#include
#include "epicsTime.h"
#include "osdTime.h"
#include "osiNTPTime.h"
@@ -117,17 +118,21 @@ double rtemsTicksPerSecond_double, rtemsTicksPerTwoSeconds_double;
* explicitly calls osdTimeRegister() at the appropriate time.
* However if we are loaded dynamically we *do* register our
* standard time providers at static constructor time; in this
- * case the tick rate will have been set already.
+ * case the network is available already.
*/
static int staticTimeRegister(void)
{
- if (rtemsTicksPerSecond != 0)
- osdTimeRegister();
-
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &rtemsTicksPerSecond);
rtemsTicksPerSecond_double = rtemsTicksPerSecond;
rtemsTicksPerTwoSeconds_double = rtemsTicksPerSecond_double * 2.0;
+ /* If networking is already up at the time static constructors
+ * are executed then we are probably run-time loaded and it's
+ * OK to osdTimeRegister() at this point.
+ */
+ if (rtems_bsdnet_ticks_per_second != 0)
+ osdTimeRegister();
+
return 1;
}
static int done = staticTimeRegister();
diff --git a/src/libCom/osi/os/WIN32/osdSock.h b/src/libCom/osi/os/WIN32/osdSock.h
index f362ed8b3..e6567e178 100644
--- a/src/libCom/osi/os/WIN32/osdSock.h
+++ b/src/libCom/osi/os/WIN32/osdSock.h
@@ -3,15 +3,12 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
-* EPICS BASE Versions 3.13.7
-* and higher are distributed subject to a Software License Agreement found
+* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
+#ifndef osdSockH
+#define osdSockH
#include
#include
@@ -25,9 +22,6 @@ extern "C" {
#endif
#include
-#ifdef __cplusplus
-}
-#endif
#define SOCKERRNO WSAGetLastError()
@@ -79,3 +73,4 @@ typedef int osiSocklen_t;
epicsShareFunc unsigned epicsShareAPI wsaMajorVersion ();
+#endif /*osdSockH*/
diff --git a/src/libCom/osi/os/WIN32/osdThread.c b/src/libCom/osi/os/WIN32/osdThread.c
index 8e4e80057..aa360cfc0 100644
--- a/src/libCom/osi/os/WIN32/osdThread.c
+++ b/src/libCom/osi/os/WIN32/osdThread.c
@@ -9,7 +9,7 @@
\*************************************************************************/
/*
- * Revision-Id: anj@aps.anl.gov-20110211223358-q0hz1pcfll3an46f
+ * Revision-Id: anj@aps.anl.gov-20111108215715-d8j6l4lycpi3gvvb
*
* Author: Jeff Hill
*
@@ -272,10 +272,6 @@ static void threadCleanupWIN32 ( void )
ellFirst ( & pGbl->threadList ) ) ) {
epicsParmCleanupWIN32 ( pParm );
}
-
- TlsFree ( pGbl->tlsIndexThreadLibraryEPICS );
-
- DeleteCriticalSection ( & pGbl->mutex );
}
/*
diff --git a/src/libCom/osi/os/WIN32/osdTime.cpp b/src/libCom/osi/os/WIN32/osdTime.cpp
index c6ba8a7b5..079cda65a 100644
--- a/src/libCom/osi/os/WIN32/osdTime.cpp
+++ b/src/libCom/osi/os/WIN32/osdTime.cpp
@@ -8,7 +8,7 @@
\*************************************************************************/
//
-// Revision-Id: johill@lanl.gov-20110115005649-10sil49p7idx8lpe
+// Revision-Id: anj@aps.anl.gov-20111129200729-1bx6zsmjnog13sf0
//
// Author: Jeff Hill
//
@@ -61,6 +61,9 @@ static int osdTimeGetCurrent ( epicsTimeStamp *pDest );
#if !defined ( MAXLONGLONG )
#define MAXLONGLONG LL_CONSTANT(0x7fffffffffffffff)
#endif
+#if !defined ( MINLONGLONG )
+#define MINLONGLONG LL_CONSTANT(~0x7fffffffffffffff)
+#endif
static const LONGLONG epicsEpochInFileTime = LL_CONSTANT(0x01b41e2a18d64000);
@@ -81,7 +84,7 @@ private:
epicsTimerQueueActive * pTimerQueue;
epicsTimer * pTimer;
bool perfCtrPresent;
-
+ static const int pllDelay; /* integer seconds */
epicsTimerNotify::expireStatus expire ( const epicsTime & );
};
@@ -91,6 +94,8 @@ static const LONGLONG EPICS_TIME_TICKS_PER_SEC = 1000000000;
static const LONGLONG ET_TICKS_PER_FT_TICK =
EPICS_TIME_TICKS_PER_SEC / FILE_TIME_TICKS_PER_SEC;
+const int currentTime :: pllDelay = 5;
+
//
// Start and register time provider
//
@@ -302,8 +307,8 @@ currentTime::currentTime () :
}
else {
errlogPrintf (
- "win32 osdTime.cpp detected questionable "
- "system date prior to EPICS epoch\n" );
+ "win32 osdTime.cpp init detected questionable "
+ "system date prior to EPICS epoch, epics time will not advance\n" );
this->epicsTimeLast = 0;
}
@@ -346,7 +351,7 @@ void currentTime::getCurrentTime ( epicsTimeStamp & dest )
// counter resolution will more than likely improve over time.
//
offset = ( MAXLONGLONG - this->lastPerfCounter )
- + ( curPerfCounter.QuadPart + MAXLONGLONG );
+ + ( curPerfCounter.QuadPart - MINLONGLONG ) + 1;
}
if ( offset < MAXLONGLONG / EPICS_TIME_TICKS_PER_SEC ) {
offset *= EPICS_TIME_TICKS_PER_SEC;
@@ -392,6 +397,8 @@ void currentTime::getCurrentTime ( epicsTimeStamp & dest )
//
epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & )
{
+ EnterCriticalSection ( & this->mutex );
+
// avoid interruptions by briefly becoming a time critical thread
LARGE_INTEGER curFileTime;
LARGE_INTEGER curPerfCounter;
@@ -407,8 +414,6 @@ epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & )
curFileTime.HighPart = ft.dwHighDateTime;
}
- EnterCriticalSection ( & this->mutex );
-
LONGLONG perfCounterDiff;
if ( curPerfCounter.QuadPart >= this->lastPerfCounterPLL ) {
perfCounterDiff = curPerfCounter.QuadPart - this->lastPerfCounterPLL;
@@ -424,7 +429,7 @@ epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & )
// counter resolution will more than likely improve over time.
//
perfCounterDiff = ( MAXLONGLONG - this->lastPerfCounterPLL )
- + ( curPerfCounter.QuadPart + MAXLONGLONG );
+ + ( curPerfCounter.QuadPart - MINLONGLONG ) + 1;
}
this->lastPerfCounterPLL = curPerfCounter.QuadPart;
@@ -432,10 +437,10 @@ epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & )
this->lastFileTimePLL = curFileTime.QuadPart;
// discard glitches
- if ( fileTimeDiff == 0 ) {
+ if ( fileTimeDiff <= 0 ) {
LeaveCriticalSection( & this->mutex );
- debugPrintf ( ( "currentTime: file time difference in PLL was zero\n" ) );
- return expireStatus ( restart, 1.0 /* sec */ );
+ debugPrintf ( ( "currentTime: file time difference in PLL was less than zero\n" ) );
+ return expireStatus ( restart, pllDelay /* sec */ );
}
LONGLONG freq = ( FILE_TIME_TICKS_PER_SEC * perfCounterDiff ) / fileTimeDiff;
@@ -449,7 +454,7 @@ epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & )
static_cast < int > ( -bound ),
static_cast < int > ( delta ),
static_cast < int > ( bound ) ) );
- return expireStatus ( restart, 1.0 /* sec */ );
+ return expireStatus ( restart, pllDelay /* sec */ );
}
// update feedback loop estimating the performance counter's frequency
@@ -473,7 +478,21 @@ epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & )
//
perfCounterDiffSinceLastFetch =
( MAXLONGLONG - this->lastPerfCounter )
- + ( curPerfCounter.QuadPart + MAXLONGLONG );
+ + ( curPerfCounter.QuadPart - MINLONGLONG ) + 1;
+ }
+
+ // discard performance counter delay measurement glitches
+ {
+ const LONGLONG expectedDly = this->perfCounterFreq * pllDelay;
+ const LONGLONG bnd = expectedDly / 4;
+ if ( perfCounterDiffSinceLastFetch <= 0 ||
+ perfCounterDiffSinceLastFetch >= expectedDly + bnd ) {
+ LeaveCriticalSection( & this->mutex );
+ debugPrintf ( ( "perf ctr measured delay out of bounds m=%d max=%d\n",
+ static_cast < int > ( perfCounterDiffSinceLastFetch ),
+ static_cast < int > ( expectedDly + bnd ) ) );
+ return expireStatus ( restart, pllDelay /* sec */ );
+ }
}
// Update the current estimated time.
@@ -482,9 +501,32 @@ epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & )
/ this->perfCounterFreq;
this->lastPerfCounter = curPerfCounter.QuadPart;
- LONGLONG epicsTimeFromCurrentFileTime =
- ( curFileTime.QuadPart - epicsEpochInFileTime ) *
- ET_TICKS_PER_FT_TICK;
+ LONGLONG epicsTimeFromCurrentFileTime;
+
+ {
+ static bool firstMessageWasSent = false;
+ if ( curFileTime.QuadPart >= epicsEpochInFileTime ) {
+ epicsTimeFromCurrentFileTime =
+ ( curFileTime.QuadPart - epicsEpochInFileTime ) *
+ ET_TICKS_PER_FT_TICK;
+ firstMessageWasSent = false;
+ }
+ else {
+ /*
+ * if the system time jumps to before the EPICS epoch
+ * then latch to the EPICS epoch printing only one
+ * warning message the first time that the issue is
+ * detected
+ */
+ if ( ! firstMessageWasSent ) {
+ errlogPrintf (
+ "win32 osdTime.cpp time PLL update detected questionable "
+ "system date prior to EPICS epoch, epics time will not advance\n" );
+ firstMessageWasSent = true;
+ }
+ epicsTimeFromCurrentFileTime = 0;
+ }
+ }
delta = epicsTimeFromCurrentFileTime - this->epicsTimeLast;
if ( delta > EPICS_TIME_TICKS_PER_SEC || delta < -EPICS_TIME_TICKS_PER_SEC ) {
@@ -537,7 +579,7 @@ epicsTimerNotify::expireStatus currentTime::expire ( const epicsTime & )
LeaveCriticalSection ( & this->mutex );
- return expireStatus ( restart, 1.0 /* sec */ );
+ return expireStatus ( restart, pllDelay /* sec */ );
}
void currentTime::startPLL ()
@@ -546,7 +588,7 @@ void currentTime::startPLL ()
if ( this->perfCtrPresent && ! this->pTimerQueue ) {
this->pTimerQueue = & epicsTimerQueueActive::allocate ( true );
this->pTimer = & this->pTimerQueue->createTimer ();
- this->pTimer->start ( *this, 1.0 );
+ this->pTimer->start ( *this, pllDelay );
}
}
diff --git a/src/libCom/osi/os/cygwin32/osdSock.h b/src/libCom/osi/os/cygwin32/osdSock.h
index 8d8326ce5..0915cc069 100644
--- a/src/libCom/osi/os/cygwin32/osdSock.h
+++ b/src/libCom/osi/os/cygwin32/osdSock.h
@@ -3,8 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
-* EPICS BASE Versions 3.13.7
-* and higher are distributed subject to a Software License Agreement found
+* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -15,10 +14,6 @@
#ifndef osdSockH
#define osdSockH
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include
#include
@@ -31,10 +26,7 @@ extern "C" {
#include
#include /* close() and others */
-#ifdef __cplusplus
-}
-#endif
-
+
typedef int SOCKET;
#define INVALID_SOCKET (-1)
#define SOCKERRNO errno
diff --git a/src/libCom/osi/os/freebsd/osdSock.h b/src/libCom/osi/os/freebsd/osdSock.h
index 8c270b72a..40df63631 100644
--- a/src/libCom/osi/os/freebsd/osdSock.h
+++ b/src/libCom/osi/os/freebsd/osdSock.h
@@ -10,10 +10,6 @@
#ifndef osdSockH
#define osdSockH
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include
#include
@@ -29,10 +25,6 @@ extern "C" {
#include /* close() and others */
-#ifdef __cplusplus
-}
-#endif
-
#ifndef IPPORT_USERRESERVED
#define IPPORT_USERRESERVED 5000
#endif
diff --git a/src/libCom/osi/os/iOS/osdSock.h b/src/libCom/osi/os/iOS/osdSock.h
index de1923967..759c51c2e 100644
--- a/src/libCom/osi/os/iOS/osdSock.h
+++ b/src/libCom/osi/os/iOS/osdSock.h
@@ -5,7 +5,7 @@
\*************************************************************************/
/*
- * Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd
+ * Revision-Id: anj@aps.anl.gov-20110909221435-fdjubbxunee9gs44
*
* Author: Eric Norum
*/
@@ -13,10 +13,6 @@
#ifndef osdSockH
#define osdSockH
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include
#include
@@ -24,8 +20,6 @@ extern "C" {
#include
#include
#include
-/*#include
-#include */
#include
#include
#include
@@ -34,10 +28,6 @@ extern "C" {
#include /* close() and others */
-#ifdef __cplusplus
-}
-#endif
-
typedef int SOCKET;
#define INVALID_SOCKET (-1)
#define SOCKERRNO errno
diff --git a/src/libCom/osi/os/posix/epicsMath.h b/src/libCom/osi/os/posix/epicsMath.h
index b09c7024b..4ed0fdc51 100644
--- a/src/libCom/osi/os/posix/epicsMath.h
+++ b/src/libCom/osi/os/posix/epicsMath.h
@@ -17,6 +17,11 @@
extern "C" {
#endif
+#ifdef isfinite
+# undef finite
+# define finite(x) isfinite(x)
+#endif
+
epicsShareExtern float epicsNAN;
epicsShareExtern float epicsINF;
diff --git a/src/libCom/osi/os/posix/osdThread.c b/src/libCom/osi/os/posix/osdThread.c
index df0321ae2..f7e47b100 100644
--- a/src/libCom/osi/os/posix/osdThread.c
+++ b/src/libCom/osi/os/posix/osdThread.c
@@ -75,6 +75,13 @@ typedef struct epicsThreadOSD {
char *name;
} epicsThreadOSD;
+#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
+typedef struct {
+ int min_pri, max_pri;
+ int policy;
+} priAvailable;
+#endif
+
static pthread_key_t getpthreadInfo;
static pthread_mutex_t onceLock;
static pthread_mutex_t listLock;
@@ -201,6 +208,101 @@ static void free_threadInfo(epicsThreadOSD *pthreadInfo)
free(pthreadInfo);
}
+#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING)
+/*
+ * The actually available range priority range (at least under linux)
+ * may be restricted by resource limitations (but that is ignored
+ * by sched_get_priority_max()). See bug #835138 which is fixed by
+ * this code.
+ */
+
+static int try_pri(int pri, int policy)
+{
+struct sched_param schedp;
+
+ schedp.sched_priority = pri;
+ return pthread_setschedparam(pthread_self(), policy, &schedp);
+}
+
+static void*
+find_pri_range(void *arg)
+{
+priAvailable *prm = arg;
+int min = sched_get_priority_min(prm->policy);
+int max = sched_get_priority_max(prm->policy);
+int low, try;
+
+ if ( -1 == min || -1 == max ) {
+ /* something is very wrong; maintain old behavior
+ * (warning message if sched_get_priority_xxx() fails
+ * and use default policy's sched_priority [even if
+ * that is likely to cause epicsThreadCreate to fail
+ * because that priority is not suitable for SCHED_FIFO]).
+ */
+ prm->min_pri = prm->max_pri = -1;
+ return 0;
+ }
+
+
+ if ( try_pri(min, prm->policy) ) {
+ /* cannot create thread at minimum priority;
+ * probably no permission to use SCHED_FIFO
+ * at all. However, we still must return
+ * a priority range accepted by the SCHED_FIFO
+ * policy. Otherwise, epicsThreadCreate() cannot
+ * detect the unsufficient permission (EPERM)
+ * and fall back to a non-RT thread (because
+ * pthread_attr_setschedparam would fail with
+ * EINVAL due to the bad priority).
+ */
+ prm->min_pri = prm->max_pri = min;
+ return 0;
+ }
+
+
+ /* Binary search through available priorities.
+ * The actually available range may be restricted
+ * by resource limitations (but that is ignored
+ * by sched_get_priority_max() [linux]).
+ */
+ low = min;
+
+ while ( low < max ) {
+ try = (max+low)/2;
+ if ( try_pri(try, prm->policy) ) {
+ max = try;
+ } else {
+ low = try + 1;
+ }
+ }
+
+ prm->min_pri = min;
+ prm->max_pri = try_pri(max, prm->policy) ? max-1 : max;
+
+ return 0;
+}
+
+static void findPriorityRange(commonAttr *a_p)
+{
+priAvailable arg;
+pthread_t id;
+void *dummy;
+int status;
+
+ arg.policy = a_p->schedPolicy;
+
+ status = pthread_create(&id, 0, find_pri_range, &arg);
+ checkStatusQuit(status, "pthread_create","epicsThreadInit");
+
+ status = pthread_join(id, &dummy);
+ checkStatusQuit(status, "pthread_join","epicsThreadInit");
+
+ a_p->minPriority = arg.min_pri;
+ a_p->maxPriority = arg.max_pri;
+}
+#endif
+
+
static void once(void)
{
epicsThreadOSD *pthreadInfo;
@@ -230,13 +332,14 @@ static void once(void)
status = pthread_attr_getschedparam(
&pcommonAttr->attr,&pcommonAttr->schedParam);
checkStatusOnce(status,"pthread_attr_getschedparam");
- pcommonAttr->maxPriority = sched_get_priority_max(pcommonAttr->schedPolicy);
+
+ findPriorityRange(pcommonAttr);
+
if(pcommonAttr->maxPriority == -1) {
pcommonAttr->maxPriority = pcommonAttr->schedParam.sched_priority;
fprintf(stderr,"sched_get_priority_max failed set to %d\n",
pcommonAttr->maxPriority);
}
- pcommonAttr->minPriority = sched_get_priority_min(pcommonAttr->schedPolicy);
if(pcommonAttr->minPriority == -1) {
pcommonAttr->minPriority = pcommonAttr->schedParam.sched_priority;
fprintf(stderr,"sched_get_priority_min failed set to %d\n",
@@ -422,7 +525,7 @@ static epicsThreadOSD *createImplicit(void)
int status;
tid = pthread_self();
- sprintf(name, "non-EPICS_%d", (int)tid);
+ sprintf(name, "non-EPICS_%ld", (long)tid);
pthreadInfo = create_threadInfo(name);
pthreadInfo->tid = tid;
pthreadInfo->osiPriority = 0;
diff --git a/src/libCom/osi/os/solaris/osdSock.h b/src/libCom/osi/os/solaris/osdSock.h
index 93cd5eeab..bffcaf367 100644
--- a/src/libCom/osi/os/solaris/osdSock.h
+++ b/src/libCom/osi/os/solaris/osdSock.h
@@ -3,8 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
-* EPICS BASE Versions 3.13.7
-* and higher are distributed subject to a Software License Agreement found
+* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
@@ -15,10 +14,6 @@
#ifndef osdSockH
#define osdSockH
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include
#include
@@ -35,10 +30,7 @@ extern "C" {
#include
#include /* close() and others */
-#ifdef __cplusplus
-}
-#endif
-
+
typedef int SOCKET;
#define INVALID_SOCKET (-1)
#define SOCKERRNO errno
diff --git a/src/libCom/osi/os/vxWorks/devLibVMEOSD.c b/src/libCom/osi/os/vxWorks/devLibVMEOSD.c
index 42d42b91f..ddd49d28d 100644
--- a/src/libCom/osi/os/vxWorks/devLibVMEOSD.c
+++ b/src/libCom/osi/os/vxWorks/devLibVMEOSD.c
@@ -7,7 +7,7 @@
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
- * Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd
+ * Revision-Id: anj@aps.anl.gov-20110721211050-gy5n916ntorc3gnp
*
* Archictecture dependent support for common device driver resources
*
@@ -50,9 +50,9 @@ static myISR *isrFetch(unsigned vectorNumber);
/*
* this routine needs to be in the symbol table
- * for this code to work correctly
+ * (i.e. not static) for this code to work correctly
*/
-static void unsolicitedHandlerEPICS(int vectorNumber);
+void unsolicitedHandlerEPICS(int vectorNumber);
/*
* this is in veclist.c
@@ -412,8 +412,10 @@ static int vxDevInterruptInUseVME (unsigned vectorNumber)
* interrupt and an interrupt arrives on the
* disconnected vector
*
+ * This routine needs to be in the symbol table
+ * (i.e. not static) for this code to work correctly
*/
-static void unsolicitedHandlerEPICS(int vectorNumber)
+void unsolicitedHandlerEPICS(int vectorNumber)
{
/*
* call logMsg() and not errMessage()
diff --git a/src/libCom/osi/os/vxWorks/osdSock.h b/src/libCom/osi/os/vxWorks/osdSock.h
index 3ebc5799a..f220ea8bd 100644
--- a/src/libCom/osi/os/vxWorks/osdSock.h
+++ b/src/libCom/osi/os/vxWorks/osdSock.h
@@ -3,8 +3,7 @@
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
-* EPICS BASE Versions 3.13.7
-* and higher are distributed subject to a Software License Agreement found
+* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -14,12 +13,10 @@
#ifndef osdSockH
#define osdSockH
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/* This is needed for vxWorks 6.8 to prevent an obnoxious compiler warning */
+#ifndef _VSB_CONFIG_FILE
#define _VSB_CONFIG_FILE <../lib/h/config/vsbConfig.h>
+#endif
#include
@@ -36,6 +33,11 @@ extern "C" {
#include
#include
#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*This following is not defined in any vxWorks header files*/
int sysClkRateGet(void);
diff --git a/src/libCom/test/Makefile b/src/libCom/test/Makefile
index 775c4e711..9bf92f528 100644
--- a/src/libCom/test/Makefile
+++ b/src/libCom/test/Makefile
@@ -52,10 +52,10 @@ epicsStringTest_SRCS += epicsStringTest.c
testHarness_SRCS += epicsStringTest.c
TESTS += epicsStringTest
-#TESTPROD_HOST += epicsTimeTest
-#epicsTimeTest_SRCS += epicsTimeTest.cpp
-#testHarness_SRCS += epicsTimeTest.cpp
-#TESTS += epicsTimeTest
+TESTPROD_HOST += epicsTimeTest
+epicsTimeTest_SRCS += epicsTimeTest.cpp
+testHarness_SRCS += epicsTimeTest.cpp
+TESTS += epicsTimeTest
TESTPROD_HOST += epicsThreadTest
epicsThreadTest_SRCS += epicsThreadTest.cpp
diff --git a/src/libCom/test/epicsErrlogTest.c b/src/libCom/test/epicsErrlogTest.c
index 08389e438..b93bee967 100644
--- a/src/libCom/test/epicsErrlogTest.c
+++ b/src/libCom/test/epicsErrlogTest.c
@@ -143,7 +143,7 @@ MAIN(epicsErrlogTest)
pvt.expect = "Testing";
pvt.checkLen = strlen(pvt.expect);
- errlogPrintfNoConsole(pvt.expect);
+ errlogPrintfNoConsole("%s", pvt.expect);
errlogFlush();
testOk1(pvt.count == 1);
@@ -153,7 +153,7 @@ MAIN(epicsErrlogTest)
pvt2.expect = pvt.expect = "Testing2";
pvt2.checkLen = pvt.checkLen = strlen(pvt.expect);
- errlogPrintfNoConsole(pvt.expect);
+ errlogPrintfNoConsole("%s", pvt.expect);
errlogFlush();
testOk1(pvt.count == 2);
@@ -165,7 +165,7 @@ MAIN(epicsErrlogTest)
pvt2.expect = "Testing3";
pvt2.checkLen = strlen(pvt2.expect);
- errlogPrintfNoConsole(pvt2.expect);
+ errlogPrintfNoConsole("%s", pvt2.expect);
errlogFlush();
testOk1(pvt.count == 2);
@@ -188,7 +188,7 @@ MAIN(epicsErrlogTest)
pvt.expect = truncmsg;
pvt.checkLen = 255;
- errlogPrintfNoConsole(longmsg);
+ errlogPrintfNoConsole("%s", longmsg);
errlogFlush();
testOk1(pvt.count == 3);
@@ -201,7 +201,7 @@ MAIN(epicsErrlogTest)
*/
pvt.jam = 1;
- errlogPrintfNoConsole(longmsg);
+ errlogPrintfNoConsole("%s", longmsg);
epicsThreadSleep(0.1);
testOk1(pvt.count == 3);
@@ -227,7 +227,7 @@ MAIN(epicsErrlogTest)
pvt.jam = 1;
for (i = 0; i < N; i++) {
- errlogPrintfNoConsole(msg);
+ errlogPrintfNoConsole("%s", msg);
}
epicsEventSignal(pvt.jammer);
@@ -258,7 +258,7 @@ MAIN(epicsErrlogTest)
testDiag("Filling with %d messages of size %d", (int) N, (int) mlen);
for (i = 0; i < N; i++) {
- errlogPrintfNoConsole(msg);
+ errlogPrintfNoConsole("%s", msg);
}
epicsThreadSleep(0.1); /* should really be a second Event */
@@ -273,10 +273,10 @@ MAIN(epicsErrlogTest)
testOk1(pvt.count == 2);
/* The buffer has space for 1 more message: sizeof(msgNode) + 256 bytes */
- errlogPrintfNoConsole(msg); /* Use up that space */
+ errlogPrintfNoConsole("%s", msg); /* Use up that space */
testDiag("Overflow the buffer");
- errlogPrintfNoConsole(msg);
+ errlogPrintfNoConsole("%s", msg);
testOk1(pvt.count == 2);
diff --git a/src/libCom/test/macEnvExpandTest.c b/src/libCom/test/macEnvExpandTest.c
index 735cd81a5..3d67efe8e 100644
--- a/src/libCom/test/macEnvExpandTest.c
+++ b/src/libCom/test/macEnvExpandTest.c
@@ -7,7 +7,7 @@
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
- * Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd
+ * Revision-Id: anj@aps.anl.gov-20111107175809-hd3rsaaa6xts2ano
*/
#include
@@ -42,7 +42,7 @@ static void check(const char *str, const char *expect)
testDiag("Got \"%s\", expected \"%s\".\n", got, expect);
pass = 0;
}
- testOk(pass, str);
+ testOk(pass, "%s", str);
}
MAIN(macEnvExpandTest)
diff --git a/src/libCom/timer/timerQueueActiveMgr.cpp b/src/libCom/timer/timerQueueActiveMgr.cpp
index e7a9b218d..a4e914fd9 100644
--- a/src/libCom/timer/timerQueueActiveMgr.cpp
+++ b/src/libCom/timer/timerQueueActiveMgr.cpp
@@ -8,7 +8,7 @@
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
- * Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd
+ * Revision-Id: anj@aps.anl.gov-20110601212718-lfoydufupy1vmabj
*
* Author Jeffrey O. Hill
* johill@lanl.gov
@@ -58,20 +58,21 @@ epicsTimerQueueActiveForC & timerQueueActiveMgr ::
void timerQueueActiveMgr ::
release ( epicsTimerQueueActiveForC & queue )
{
- timerQueueActiveMgrPrivate * pPriv = & queue;
{
epicsGuard < epicsMutex > locker ( this->mutex );
assert ( queue.timerQueueActiveMgrPrivate::referenceCount > 0u );
queue.timerQueueActiveMgrPrivate::referenceCount--;
- if ( queue.timerQueueActiveMgrPrivate::referenceCount == 0u ) {
- if ( queue.sharingOK () ) {
- this->sharedQueueList.remove ( queue );
- }
+ if ( queue.timerQueueActiveMgrPrivate::referenceCount > 0u ) {
+ return;
+ }
+ else if ( queue.sharingOK () ) {
+ this->sharedQueueList.remove ( queue );
}
}
// delete only after we release the guard in case the embedded
// reference is the last one and this object is destroyed
// as a side effect
+ timerQueueActiveMgrPrivate * pPriv = & queue;
delete pPriv;
}
diff --git a/src/makeBaseApp/makeBaseApp.pl b/src/makeBaseApp/makeBaseApp.pl
index a176d9830..390634470 100755
--- a/src/makeBaseApp/makeBaseApp.pl
+++ b/src/makeBaseApp/makeBaseApp.pl
@@ -2,12 +2,17 @@ eval 'exec perl -S $0 ${1+"$@"}' # -*- Mode: perl -*-
if $running_under_some_shell; # makeBaseApp
# Authors: Ralph Lange, Marty Kraimer, Andrew Johnson and Janet Anderson
-# Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd
+# Revision-Id: anj@aps.anl.gov-20111108235119-b2yn7ucijl5dbsuu
+
+use FindBin qw($Bin);
+use lib ("$Bin/../../lib/perl", $Bin);
use Cwd;
use Getopt::Std;
use File::Find;
-use File::Path;
+use File::Path 'mkpath';
+use EPICS::Path;
+use EPICS::Release;
$app_top = cwd();
@@ -17,10 +22,8 @@ $app_top = cwd();
$bad_ident_chars = '[^0-9A-Za-z_]';
&GetUser; # Ensure we know who's in charge
-&readRelease("configure/RELEASE", \%release, \@apps) if (-r "configure/RELEASE");
-&readRelease("configure/RELEASE.$ENV{EPICS_HOST_ARCH}", \%release, \@apps)
- if (-r "configure/RELEASE.$ENV{EPICS_HOST_ARCH}");
-&expandRelease(\%release, \@apps);
+&readReleaseFiles("configure/RELEASE", \%release, \@apps);
+&expandRelease(\%release);
&get_commandline_opts; # Check command-line options
#
@@ -297,57 +300,6 @@ sub get_commandline_opts { #no args
. "EPICS-Base: $epics_base\n\n" if $opt_d;
}
-#
-# Parse a configure/RELEASE file.
-#
-# NB: This subroutine also appears in base/configure/tools/convertRelease.pl
-# If you make changes here, they will be needed there as well.
-#
-sub readRelease {
- my ($file, $Rmacros, $Rapps) = @_;
- # $Rmacros is a reference to a hash, $Rapps a ref to an array
- my ($pre, $var, $post, $macro, $path);
- local *IN;
- open(IN, $file) or die "Can't open $file: $!\n";
- while () {
- chomp;
- s/\r$//; # Shouldn't need this, but sometimes...
- s/\s*#.*$//; # Remove trailing comments
- next if /^\s*$/; # Skip blank lines
-
- # Expand all already-defined macros in the line:
- while (($pre,$var,$post) = /(.*)\$\((\w+)\)(.*)/) {
- last unless (exists $Rmacros->{$var});
- $_ = $pre . $Rmacros->{$var} . $post;
- }
-
- # Handle " = "
- ($macro, $path) = /^\s*(\w+)\s*=\s*(.*)/;
- if ($macro ne "") {
- $Rmacros->{$macro} = $path;
- push @$Rapps, $macro;
- next;
- }
- # Handle "include " syntax
- ($path) = /^\s*include\s+(.*)/;
- &readRelease($path, $Rmacros, $Rapps) if (-r $path);
- }
- close IN;
-}
-
-sub expandRelease {
- my ($Rmacros, $Rapps) = @_;
- # $Rmacros is a reference to a hash, $Rapps a ref to an array
-
- # Expand any (possibly nested) macros that were defined after use
- while (($macro, $path) = each %$Rmacros) {
- while (($pre,$var,$post) = $path =~ /(.*)\$\((\w+)\)(.*)/) {
- $path = $pre . $Rmacros->{$var} . $post;
- $Rmacros->{$macro} = $path;
- }
- }
-}
-
#
# List application types
#
@@ -480,29 +432,3 @@ sub GetUser {
}
die "No user name" unless $user;
}
-
-# Path rewriting rules for various OSs
-# These functions are duplicated in configure/convertRelease.pl
-sub UnixPath {
- my ($newpath) = @_;
- if ($^O eq 'cygwin') {
- $newpath =~ s{\\}{/}go;
- $newpath =~ s{^([a-zA-Z]):/}{/cygdrive/$1/};
- } elsif ($^O eq 'MSWin32') {
- $newpath =~ s{\\}{/}go;
- } elsif ($^O eq 'sunos') {
- $newpath =~ s{^/tmp_mnt/}{/};
- }
- return $newpath;
-}
-
-sub LocalPath {
- my ($newpath) = @_;
- if ($^O eq "cygwin") {
- $newpath =~ s{^/cygdrive/([a-zA-Z])/}{$1:/};
- } elsif ($^O eq "darwin") {
- # These rules are likely to be site-specific
- $newpath =~ s{^/private/var/auto\.home/}{/home/}; # APS
- }
- return $newpath;
-}
diff --git a/src/makeBaseApp/top/caServerApp/Makefile b/src/makeBaseApp/top/caServerApp/Makefile
index 8584b8804..0195112ac 100644
--- a/src/makeBaseApp/top/caServerApp/Makefile
+++ b/src/makeBaseApp/top/caServerApp/Makefile
@@ -17,15 +17,15 @@ PROD_LIBS += $(EPICS_BASE_HOST_LIBS)
#
# Added ws2_32 winmm user32 for the non-dll build
#
-SYS_PROD_LIBS_WIN32 += ws2_32 advapi32 user32
+PROD_SYS_LIBS_WIN32 += ws2_32 advapi32 user32
-SRCS += main.cc
-SRCS += exServer.cc
-SRCS += exPV.cc
-SRCS += exVectorPV.cc
-SRCS += exScalarPV.cc
-SRCS += exAsyncPV.cc
-SRCS += exChannel.cc
+casexample_SRCS += main.cc
+casexample_SRCS += exServer.cc
+casexample_SRCS += exPV.cc
+casexample_SRCS += exVectorPV.cc
+casexample_SRCS += exScalarPV.cc
+casexample_SRCS += exAsyncPV.cc
+casexample_SRCS += exChannel.cc
PROD_HOST = casexample
diff --git a/src/misc/iocInit.c b/src/misc/iocInit.c
index a31cf074f..2183d248f 100644
--- a/src/misc/iocInit.c
+++ b/src/misc/iocInit.c
@@ -6,7 +6,7 @@
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
-/* Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd */
+/* Revision-Id: anj@aps.anl.gov-20110926214215-c1ma6lbqwz4dkeqx */
/*
* Original Author: Marty Kraimer
* Date: 06-01-91
@@ -44,6 +44,7 @@
#include "dbLock.h"
#include "devSup.h"
#include "drvSup.h"
+#include "menuConvert.h"
#include "menuPini.h"
#include "registryRecordType.h"
#include "registryDeviceSupport.h"
@@ -68,6 +69,7 @@ static enum {
} iocState = iocVirgin;
/* define forward references*/
+static int checkDatabase(dbBase *pdbbase);
static void initDrvSup(void);
static void initRecSup(void);
static void initDevSup(void);
@@ -98,8 +100,8 @@ int iocBuild(void)
}
errlogPrintf("Starting iocInit\n");
- if (!pdbbase) {
- errlogPrintf("iocBuild: Aborting, no database loaded!\n");
+ if (checkDatabase(pdbbase)) {
+ errlogPrintf("iocBuild: Aborting, bad database definition (DBD)!\n");
return -1;
}
epicsSignalInstallSigHupIgnore();
@@ -203,6 +205,83 @@ int iocPause(void)
return 0;
}
+/*
+ * Database sanity checks
+ *
+ * This is not an attempt to sanity-check the whole .dbd file, only
+ * two menus normally get modified by users: menuConvert and menuScan.
+ *
+ * The menuConvert checks were added to flag problems with IOCs
+ * converted from 3.13.x, where the SLOPE choice didn't exist.
+ *
+ * The menuScan checks make sure the user didn't fiddle too much
+ * when creating new periodic scan choices.
+ */
+
+static int checkDatabase(dbBase *pdbbase)
+{
+ const dbMenu *pMenu;
+
+ if (!pdbbase) {
+ errlogPrintf("checkDatabase: No database definitions loaded.\n");
+ return -1;
+ }
+
+ pMenu = dbFindMenu(pdbbase, "menuConvert");
+ if (!pMenu) {
+ errlogPrintf("checkDatabase: menuConvert not defined.\n");
+ return -1;
+ }
+ if (pMenu->nChoice <= menuConvertLINEAR) {
+ errlogPrintf("checkDatabase: menuConvert has too few choices.\n");
+ return -1;
+ }
+ if (strcmp(pMenu->papChoiceName[menuConvertNO_CONVERSION],
+ "menuConvertNO_CONVERSION")) {
+ errlogPrintf("checkDatabase: menuConvertNO_CONVERSION doesn't match.\n");
+ return -1;
+ }
+ if (strcmp(pMenu->papChoiceName[menuConvertSLOPE], "menuConvertSLOPE")) {
+ errlogPrintf("checkDatabase: menuConvertSLOPE doesn't match.\n");
+ return -1;
+ }
+ if (strcmp(pMenu->papChoiceName[menuConvertLINEAR], "menuConvertLINEAR")) {
+ errlogPrintf("checkDatabase: menuConvertLINEAR doesn't match.\n");
+ return -1;
+ }
+
+ pMenu = dbFindMenu(pdbbase, "menuScan");
+ if (!pMenu) {
+ errlogPrintf("checkDatabase: menuScan not defined.\n");
+ return -1;
+ }
+ if (pMenu->nChoice <= menuScanI_O_Intr) {
+ errlogPrintf("checkDatabase: menuScan has too few choices.\n");
+ return -1;
+ }
+ if (strcmp(pMenu->papChoiceName[menuScanPassive],
+ "menuScanPassive")) {
+ errlogPrintf("checkDatabase: menuScanPassive doesn't match.\n");
+ return -1;
+ }
+ if (strcmp(pMenu->papChoiceName[menuScanEvent],
+ "menuScanEvent")) {
+ errlogPrintf("checkDatabase: menuScanEvent doesn't match.\n");
+ return -1;
+ }
+ if (strcmp(pMenu->papChoiceName[menuScanI_O_Intr],
+ "menuScanI_O_Intr")) {
+ errlogPrintf("checkDatabase: menuScanI_O_Intr doesn't match.\n");
+ return -1;
+ }
+ if (pMenu->nChoice <= SCAN_1ST_PERIODIC) {
+ errlogPrintf("checkDatabase: menuScan has no periodic choices.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
static void initDrvSup(void) /* Locate all driver support entry tables */
{
@@ -506,6 +585,7 @@ static void doCloseLinks(dbRecordType *pdbRecordType, dbCommon *precord,
devSup *pdevSup;
struct dsxt *pdsxt;
int j;
+ int locked = 0;
for (j = 0; j < pdbRecordType->no_links; j++) {
dbFldDes *pdbFldDes =
@@ -513,7 +593,12 @@ static void doCloseLinks(dbRecordType *pdbRecordType, dbCommon *precord,
DBLINK *plink = (DBLINK *)((char *)precord + pdbFldDes->offset);
if (plink->type == CA_LINK) {
+ if (!locked) {
+ dbScanLock(precord);
+ locked = 1;
+ }
dbCaRemoveLink(plink);
+ plink->type = CONSTANT;
}
}
@@ -521,8 +606,16 @@ static void doCloseLinks(dbRecordType *pdbRecordType, dbCommon *precord,
(pdevSup = dbDSETtoDevSup(pdbRecordType, precord->dset)) &&
(pdsxt = pdevSup->pdsxt) &&
pdsxt->del_record) {
+ if (!locked) {
+ dbScanLock(precord);
+ locked = 1;
+ }
pdsxt->del_record(precord);
}
+ if (locked) {
+ precord->pact = TRUE;
+ dbScanUnlock(precord);
+ }
}
static void exitDatabase(void *dummy)
diff --git a/src/rec/Makefile b/src/rec/Makefile
index 0d4b78aa8..325bc750b 100644
--- a/src/rec/Makefile
+++ b/src/rec/Makefile
@@ -1,10 +1,9 @@
#*************************************************************************
-# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
+# Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
-# EPICS BASE Versions 3.13.7
-# and higher are distributed subject to a Software License Agreement found
+# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
TOP=../..
diff --git a/src/rec/calcoutRecord.c b/src/rec/calcoutRecord.c
index 95b7c0d10..062580c76 100644
--- a/src/rec/calcoutRecord.c
+++ b/src/rec/calcoutRecord.c
@@ -197,8 +197,6 @@ static long init_record(calcoutRecord *prec, int pass)
callbackSetUser(prec, &prpvt->checkLinkCb);
prpvt->cbScheduled = 0;
- prec->epvt = eventNameToHandle(prec->oevt);
-
if (pcalcoutDSET->init_record) pcalcoutDSET->init_record(prec);
prec->pval = prec->val;
prec->mlst = prec->val;
@@ -359,9 +357,6 @@ static long special(DBADDR *paddr, int after)
}
db_post_events(prec, plinkValid, DBE_VALUE);
return 0;
- case(calcoutRecordOEVT):
- prec->epvt = eventNameToHandle(prec->oevt);
- return 0;
default:
recGblDbaddrError(S_db_badChoice, paddr, "calc: special");
return(S_db_badChoice);
@@ -545,21 +540,27 @@ static void execOutput(calcoutRecord *prec)
if (prec->nsev < INVALID_ALARM ) {
/* Output the value */
status = writeValue(prec);
- /* post output event if set */
- if (prec->epvt) postEvent(prec->epvt);
+ /* post event if output event != 0 */
+ if (prec->oevt > 0) {
+ post_event((int)prec->oevt);
+ }
} else switch (prec->ivoa) {
case menuIvoaContinue_normally:
status = writeValue(prec);
- /* post output event if set */
- if (prec->epvt) postEvent(prec->epvt);
+ /* post event if output event != 0 */
+ if (prec->oevt > 0) {
+ post_event((int)prec->oevt);
+ }
break;
case menuIvoaDon_t_drive_outputs:
break;
case menuIvoaSet_output_to_IVOV:
prec->oval = prec->ivov;
status = writeValue(prec);
- /* post output event if set */
- if (prec->epvt) postEvent(prec->epvt);
+ /* post event if output event != 0 */
+ if (prec->oevt > 0) {
+ post_event((int)prec->oevt);
+ }
break;
default:
status = -1;
diff --git a/src/rec/calcoutRecord.dbd b/src/rec/calcoutRecord.dbd
index 8b80094d1..fc393a782 100644
--- a/src/rec/calcoutRecord.dbd
+++ b/src/rec/calcoutRecord.dbd
@@ -255,19 +255,10 @@ recordtype(calcout) {
prompt("OCAL Valid")
interest(1)
}
- field(OEVT,DBF_STRING) {
+ field(OEVT,DBF_USHORT) {
prompt("Event To Issue")
promptgroup(GUI_CLOCK)
- special(SPC_MOD)
asl(ASL0)
- size(40)
- }
- %#include "dbScan.h"
- field(EPVT, DBF_NOACCESS) {
- prompt("Event private")
- special(SPC_NOMOD)
- interest(4)
- extra("EVENTPVT epvt")
}
field(IVOA,DBF_MENU) {
prompt("INVALID output action")
diff --git a/src/rec/compressRecord.c b/src/rec/compressRecord.c
index d1ce9f57d..7c00a21d8 100644
--- a/src/rec/compressRecord.c
+++ b/src/rec/compressRecord.c
@@ -7,7 +7,7 @@
* in file LICENSE that is included with this distribution.
\*************************************************************************/
-/* Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd */
+/* Revision-Id: anj@aps.anl.gov-20110608161626-57vf3rfrk73ppemb */
/*
* Original Author: Bob Dalesio
* Date: 7-14-89
@@ -92,12 +92,14 @@ static void reset(compressRecord *prec)
static void monitor(compressRecord *prec)
{
- unsigned short monitor_mask;
+ unsigned short alarm_mask = recGblResetAlarms(prec);
+ unsigned short monitor_mask = alarm_mask | DBE_LOG | DBE_VALUE;
- monitor_mask = recGblResetAlarms(prec);
- monitor_mask |= (DBE_LOG|DBE_VALUE);
- if(monitor_mask) db_post_events(prec,prec->bptr,monitor_mask);
- return;
+ if (alarm_mask || prec->nuse != prec->ouse) {
+ db_post_events(prec, &prec->nuse, monitor_mask);
+ prec->ouse = prec->nuse;
+ }
+ db_post_events(prec, prec->bptr, monitor_mask);
}
static void put_value(compressRecord *prec,double *psource, epicsInt32 n)
diff --git a/src/rec/compressRecord.dbd b/src/rec/compressRecord.dbd
index e3bcd438e..45f5a2957 100644
--- a/src/rec/compressRecord.dbd
+++ b/src/rec/compressRecord.dbd
@@ -95,6 +95,10 @@ recordtype(compress) {
prompt("Number Used")
special(SPC_NOMOD)
}
+ field(OUSE,DBF_ULONG) {
+ prompt("Old Number Used")
+ special(SPC_NOMOD)
+ }
field(BPTR,DBF_NOACCESS) {
prompt("Buffer Pointer")
special(SPC_NOMOD)
diff --git a/src/rec/eventRecord.c b/src/rec/eventRecord.c
index 9b137d6aa..01a71daa4 100644
--- a/src/rec/eventRecord.c
+++ b/src/rec/eventRecord.c
@@ -32,7 +32,6 @@
#include "errMdef.h"
#include "recSup.h"
#include "recGbl.h"
-#include "special.h"
#include "menuYesNo.h"
#define GEN_SIZE_OFFSET
#include "eventRecord.h"
@@ -44,7 +43,7 @@
#define initialize NULL
static long init_record(eventRecord *, int);
static long process(eventRecord *);
-static long special(DBADDR *, int);
+#define special NULL
static long get_value(eventRecord *, struct valueDes *);
#define cvt_dbaddr NULL
#define get_array_info NULL
@@ -104,11 +103,9 @@ static long init_record(eventRecord *prec, int pass)
}
if (prec->siol.type == CONSTANT) {
- recGblInitConstantLink(&prec->siol,DBF_STRING,&prec->sval);
+ recGblInitConstantLink(&prec->siol,DBF_USHORT,&prec->sval);
}
- prec->epvt = eventNameToHandle(prec->val);
-
if( (pdset=(struct eventdset *)(prec->dset)) && (pdset->init_record) )
status=(*pdset->init_record)(prec);
return(status);
@@ -126,7 +123,7 @@ static long process(eventRecord *prec)
if ( !pact && prec->pact ) return(0);
prec->pact = TRUE;
- postEvent(prec->epvt);
+ if(prec->val>0) post_event((int)prec->val);
recGblGetTimeStamp(prec);
@@ -140,22 +137,10 @@ static long process(eventRecord *prec)
return(status);
}
-
-static long special(DBADDR *paddr, int after)
-{
- eventRecord *prec = (eventRecord *)paddr->precord;
-
- if (!after) return 0;
- if (dbGetFieldIndex(paddr) == eventRecordVAL) {
- prec->epvt = eventNameToHandle(prec->val);
- }
- return 0;
-}
-
static long get_value(eventRecord *prec, struct valueDes *pvdes)
{
- pvdes->field_type = DBF_STRING;
+ pvdes->field_type = DBF_USHORT;
pvdes->no_elements=1;
pvdes->pvalue = (void *)(&prec->val);
return(0);
@@ -192,13 +177,10 @@ static long readValue(eventRecord *prec)
return(status);
}
if (prec->simm == menuYesNoYES){
- status=dbGetLink(&(prec->siol),DBR_STRING,
+ status=dbGetLink(&(prec->siol),DBR_USHORT,
&(prec->sval),0,0);
if (status==0) {
- if (strcmp(prec->sval, prec->val) != 0) {
- strcpy(prec->val, prec->sval);
- prec->epvt = eventNameToHandle(prec->val);
- }
+ prec->val=prec->sval;
prec->udf=FALSE;
}
} else {
diff --git a/src/rec/eventRecord.dbd b/src/rec/eventRecord.dbd
index f7bbb7ee7..f63355900 100644
--- a/src/rec/eventRecord.dbd
+++ b/src/rec/eventRecord.dbd
@@ -9,19 +9,10 @@
#*************************************************************************
recordtype(event) {
include "dbCommon.dbd"
- field(VAL,DBF_STRING) {
- prompt("Event Name To Post")
+ field(VAL,DBF_USHORT) {
+ prompt("Event Number To Post")
promptgroup(GUI_INPUTS)
- special(SPC_MOD)
asl(ASL0)
- size(40)
- }
- %#include "dbScan.h"
- field(EPVT, DBF_NOACCESS) {
- prompt("Event private")
- special(SPC_NOMOD)
- interest(4)
- extra("EVENTPVT epvt")
}
field(INP,DBF_INLINK) {
prompt("Input Specification")
@@ -33,9 +24,8 @@ recordtype(event) {
promptgroup(GUI_INPUTS)
interest(1)
}
- field(SVAL,DBF_STRING) {
+ field(SVAL,DBF_USHORT) {
prompt("Simulation Value")
- size(40)
}
field(SIML,DBF_INLINK) {
prompt("Sim Mode Location")
diff --git a/src/softIoc/makeInstallDir.pl b/src/softIoc/makeInstallDir.pl
index c9d6d2a75..96c305711 100644
--- a/src/softIoc/makeInstallDir.pl
+++ b/src/softIoc/makeInstallDir.pl
@@ -14,6 +14,8 @@ die "Path to INSTALL_LOCATION missing\n" unless @ARGV == 1;
my $path = shift;
$path =~ s/\\/\\\\/gx;
+$path =~ s/^'//;
+$path =~ s/'$//;
print "/* THIS IS A GENERATED FILE. DO NOT EDIT! */\n",
"\n",
diff --git a/src/tools/EPICS/Path.pm b/src/tools/EPICS/Path.pm
index e7d027a6e..a8bfdb508 100644
--- a/src/tools/EPICS/Path.pm
+++ b/src/tools/EPICS/Path.pm
@@ -5,7 +5,7 @@
# in file LICENSE that is included with this distribution.
#*************************************************************************
-# Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd
+# Revision-Id: anj@aps.anl.gov-20110523213458-3lhktmvu73otws64
use Carp;
use Cwd qw(getcwd abs_path);
@@ -64,7 +64,6 @@ put into a file. It converts paths from the Unix form that Perl understands to
any necessary external representation, and also removes automounter prefixes to
put the path into its canonical form.
-On cygwin we convert cygdrive paths to their equivalent Windows drive specs.
Before Leopard, the Mac OS X automounter inserted a verbose prefix, and in case
anyone is still using SunOS it adds its own prefix as well.
@@ -72,9 +71,7 @@ anyone is still using SunOS it adds its own prefix as well.
sub LocalPath {
my ($newpath) = @_;
- if ($^O eq 'cygwin') {
- $newpath =~ s{^/cygdrive/([a-zA-Z])/}{$1:/};
- } elsif ($^O eq 'darwin') {
+ if ($^O eq 'darwin') {
# Darwin automounter
$newpath =~ s{^/private/var/auto\.}{/};
} elsif ($^O eq 'sunos') {
diff --git a/src/tools/convertRelease.pl b/src/tools/convertRelease.pl
index d84c98486..dfe6e6224 100644
--- a/src/tools/convertRelease.pl
+++ b/src/tools/convertRelease.pl
@@ -9,7 +9,7 @@ eval 'exec perl -S $0 ${1+"$@"}' # -*- Mode: perl -*-
# in file LICENSE that is included with this distribution.
#*************************************************************************
#
-# Revision-Id: anj@aps.anl.gov-20101216230215-3416a76xyxueijr9
+# Revision-Id: anj@aps.anl.gov-20110713153813-utpd5swcmji6ce4l
#
# Convert configure/RELEASE file(s) into something else.
#
@@ -19,7 +19,7 @@ use strict;
use FindBin qw($Bin);
use lib ("$Bin/../../lib/perl", $Bin);
-use Cwd qw(cwd abs_path);
+use Cwd qw(cwd);
use Getopt::Std;
use EPICS::Path;
use EPICS::Release;
@@ -215,7 +215,7 @@ sub checkRelease {
while (my ($parent, $ppath) = each %check) {
if (exists $macros{$parent} &&
- abs_path($macros{$parent}) ne abs_path($ppath)) {
+ AbsPath($macros{$parent}) ne AbsPath($ppath)) {
print "\n" unless ($status);
print "Definition of $parent conflicts with $app support.\n";
print "In this application a RELEASE file defines\n";
diff --git a/src/tools/fullPathName.pl b/src/tools/fullPathName.pl
index c35b738bd..4ff31ab24 100644
--- a/src/tools/fullPathName.pl
+++ b/src/tools/fullPathName.pl
@@ -7,7 +7,7 @@ eval 'exec perl -S -w $0 ${1+"$@"}' # -*- Mode: perl -*-
# in file LICENSE that is included with this distribution.
#*************************************************************************
-# Revision-Id: anj@aps.anl.gov-20101216230215-3416a76xyxueijr9
+# Revision-Id: anj@aps.anl.gov-20110608171518-onrlqi2bcf4wmbhs
# Determines an absolute pathname for its argument,
# which may be either a relative or absolute path and
@@ -29,7 +29,7 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
my $path = AbsPath(shift);
# Escape shell special characters unless on Windows, which doesn't allow them.
-$path =~ s/([!"\$&'\(\)*,:;<=>?\[\\\]^`{|}])/\\\1/g unless $^O eq 'MSWin32';
+$path =~ s/([!"\$&'\(\)*,:;<=>?\[\\\]^`{|}])/\\$1/g unless $^O eq 'MSWin32';
print "$path\n";
diff --git a/src/tools/installEpics.pl b/src/tools/installEpics.pl
index 248e662f7..3340bd5c3 100644
--- a/src/tools/installEpics.pl
+++ b/src/tools/installEpics.pl
@@ -1,11 +1,10 @@
#!/usr/bin/perl
#*************************************************************************
-# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
+# Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
-# EPICS BASE Versions 3.13.7
-# and higher are distributed subject to a Software License Agreement found
+# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
#
@@ -62,18 +61,13 @@ foreach $source ( @files )
$basename=$source;
$basename=~s'.*[/\\]'';
$target = "$install_dir/$basename";
+ $temp = "$target.$$";
- # The Win32 filesystem seems to be 'slow',
- # i.e. $target may look like 'up to date'
- # unless you wait an hour.
- # -> skip this test on WIN32 ?
- #if (-f $target and $^O ne "MSWin32")
if (-f $target)
{
- if (-M $target < -M $source and
+ if (-M $target < -M $source and
-C $target < -C $source)
{
- print "$target is up to date\n";
next;
}
else
@@ -84,8 +78,9 @@ foreach $source ( @files )
}
}
- # print "Installing $source into $install_dir\n";
- copy ($source, $target) or die "Copy failed";
+ # Using copy + rename fixes problems with parallel builds:
+ copy ($source, $temp) or die "Copy failed: $!\n";
+ rename ($temp, $target) or die "Rename failed: $!\n";
# chmod 0555 DOES work on WIN32, but:
# Another chmod 0777 to make it write- and deletable
diff --git a/src/tools/makeDbDepends.pl b/src/tools/makeDbDepends.pl
index 729814326..16834de10 100644
--- a/src/tools/makeDbDepends.pl
+++ b/src/tools/makeDbDepends.pl
@@ -3,31 +3,22 @@ eval 'exec perl -S $0 ${1+"$@"}' # -*- Mode: perl -*-
# Called from within RULES.Db in the Db directories.
# Searches .substitutions and .template files (from the command line) for
-# "file xxx {" entries to create a DEPENDS file
-# and
-# 'include "xxx"' entries to create a DEPENDS file
+# file ["']xxx["'] {
+# and
+# include "xxx"
+# entries to include in the DEPENDS file
+use strict;
-$target = $ARGV[0];
-shift @ARGV;
+my $target = shift @ARGV;
+my %depends;
-
-foreach $file (@ARGV) {
- open(IN, "<$file") or die "Cannot open $file: $!";
- @infile = ;
- close IN or die "Cannot close $file: $!";
-
- @depends = grep { s/^\s*file\s*(.*)\s*\{.*$/\1/ } @infile;
- chomp @depends;
-
- if (@depends) {
- print "$target: @depends\n";
- }
-
- @depends2 = grep { s/^\s*include\s*\"\s*(.*)\s*\".*$/\1/ } @infile;
- chomp @depends2;
-
- if (@depends2) {
- print "$target: @depends2\n";
- }
+while (my $line = <>) {
+ $depends{$2}++ if $line =~ m/^\s*file\s*(["']?)(.*)\1/;
+ $depends{$1}++ if $line =~ m/^\s*include\s+"(.*)"/;
+}
+
+if (%depends) {
+ my @depends = keys %depends;
+ print "$target: @depends\n";
}
diff --git a/src/util/iocLogServer.c b/src/util/iocLogServer.c
index dd2a14679..55a6b83b6 100644
--- a/src/util/iocLogServer.c
+++ b/src/util/iocLogServer.c
@@ -1,17 +1,16 @@
/*************************************************************************\
-* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
+* Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
-* EPICS BASE Versions 3.13.7
-* and higher are distributed subject to a Software License Agreement found
+* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* iocLogServer.c */
-/* base/src/util Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd */
+/* Revision-Id: anj@aps.anl.gov-20110601205510-1lmsijq2jslrhe9m */
/*
- * archive logMsg() from several IOC's to a common rotating file
+ * archive logMsg() from several IOC's to a common rotating file
*
*
* Author: Jeffrey O. Hill
@@ -903,40 +902,35 @@ static void serviceSighupRequest(void *pParam)
}
/*
- * If it's changed, open the new file.
+ * Try (re)opening the file.
*/
- if (strcmp(ioc_log_file_name, pserver->outfile) == 0) {
+ status = openLogFile(pserver);
+ if(status<0){
fprintf(stderr,
- "iocLogServer: log file name unchanged; not re-opened\n");
- }
- else {
+ "File access problems to `%s' because `%s'\n",
+ ioc_log_file_name,
+ strerror(errno));
+ /* Revert to old filename */
+ strcpy(ioc_log_file_name, pserver->outfile);
status = openLogFile(pserver);
if(status<0){
fprintf(stderr,
- "File access problems to `%s' because `%s'\n",
+ "File access problems to `%s' because `%s'\n",
ioc_log_file_name,
strerror(errno));
- strcpy(ioc_log_file_name, pserver->outfile);
- status = openLogFile(pserver);
- if(status<0){
- fprintf(stderr,
- "File access problems to `%s' because `%s'\n",
- ioc_log_file_name,
- strerror(errno));
- return;
- }
- else {
- fprintf(stderr,
- "iocLogServer: re-opened old log file %s\n",
- ioc_log_file_name);
- }
+ return;
}
else {
fprintf(stderr,
- "iocLogServer: opened new log file %s\n",
+ "iocLogServer: re-opened old log file %s\n",
ioc_log_file_name);
}
}
+ else {
+ fprintf(stderr,
+ "iocLogServer: opened new log file %s\n",
+ ioc_log_file_name);
+ }
}
diff --git a/startup/EpicsHostArch b/startup/EpicsHostArch
index ae25ea7cd..6b102b9b9 100755
--- a/startup/EpicsHostArch
+++ b/startup/EpicsHostArch
@@ -1,11 +1,10 @@
#!/bin/sh
#*************************************************************************
-# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
+# Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
-# EPICS BASE Versions 3.13.7
-# and higher are distributed subject to a Software License Agreement found
+# EPICS BASE is distributed subject to a Software License Agreement found
# in file LICENSE that is included with this distribution.
#*************************************************************************
#
@@ -37,9 +36,9 @@ case $sysname in
Darwin )
os=darwin
cpu=`uname -m`
- case "$cpu" in
+ case $cpu in
"Power Macintosh") cpu=ppc ;;
- "i386") cpu=x86 ;;
+ i386 | x86_64 ) cpu=x86 ;;
esac
echo ${os}-${cpu}${suffix}
;;
diff --git a/startup/EpicsHostArch.pl b/startup/EpicsHostArch.pl
index 9e24882cb..50ebe57fe 100755
--- a/startup/EpicsHostArch.pl
+++ b/startup/EpicsHostArch.pl
@@ -1,7 +1,7 @@
eval 'exec perl -S $0 ${1+"$@"}' # -*- Mode: perl -*-
if $running_under_some_shell; # EpicsHostArch.pl
#*************************************************************************
-# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
+# Copyright (c) 2011 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
@@ -9,7 +9,7 @@ eval 'exec perl -S $0 ${1+"$@"}' # -*- Mode: perl -*-
# in file LICENSE that is included with this distribution.
#*************************************************************************
-# Revision-Id: anj@aps.anl.gov-20101014190140-s9gxgtnoyhbck6id
+# Revision-Id: anj@aps.anl.gov-20110627200954-dl56anmi4ikl332u
# Returns the Epics host architecture suitable
# for assigning to the EPICS_HOST_ARCH variable
@@ -34,6 +34,7 @@ sub GetEpicsHostArch { # no args
my($kernel, $hostname, $release, $version, $cpu) = POSIX::uname();
if ($cpu =~ m/Power Macintosh/) { return "darwin-ppc"; }
elsif ($cpu =~ m/i386/) { return "darwin-x86"; }
+ elsif ($cpu =~ m/x86_64/) { return "darwin-x86"; }
else { return "unsupported"; }
} else { return "unsupported"; }
}