Compare commits

..

277 Commits

Author SHA1 Message Date
Andrew Johnson
ee91b29fe0 Clear version snapshot for 3.16.1 final release 2017-06-02 14:54:58 -05:00
Andrew Johnson
0c9254f768 Final documentation updates 2017-06-02 14:53:11 -05:00
Andrew Johnson
073f3f33a6 Merge 3.15 branch into 3.16 2017-06-01 16:42:10 -05:00
Andrew Johnson
77c00faabe Merge 3.15 branch into 3.16 2017-05-30 17:17:59 -05:00
Andrew Johnson
117e294ec6 Set asynSoftTest plan 2017-05-27 21:59:44 -05:00
Andrew Johnson
afdb6af0c7 Fix buffer size issue in devI64inSoftCallback 2017-05-27 21:56:10 -05:00
Andrew Johnson
b97f04464c Add asyncSoftTest to record test harness 2017-05-27 21:45:46 -05:00
Andrew Johnson
b2473f939f Rename asyncSoft main routine 2017-05-27 21:41:37 -05:00
Andrew Johnson
c05fa4ddb7 Add tests for Async Soft Channel devices 2017-05-27 20:57:42 -05:00
Andrew Johnson
c8fcfbea9f Convert all Async Soft Channel input devices to use link support 2017-05-27 20:35:53 -05:00
Andrew Johnson
07aa712b07 Convert int64out Async Soft Channel device to use link support 2017-05-27 20:33:38 -05:00
Michael Davidsaver
1865e84321 ioc/db: dbLockCleanupRecords() warn only if lockSets remain 2017-05-24 18:41:32 -04:00
Andrew Johnson
7efba21d1f Fix 32-bit issue in linkInitTest.c 2017-05-24 16:41:34 -04:00
Andrew Johnson
c22c94a3aa Convert devI64inSoft for Link Support
Includes tests to make sure it actually works
2017-05-24 00:20:38 -04:00
Andrew Johnson
542353aedb Fix aai constant initialization
The aai record is "special" and does things its own way.
These changes let it support {const:[...]} initialization without
breaking regular input link types which could be initialized twice
without the new DBLINK_FLAG_INITIALIZED guard in dbInitLink().

Also adds tests for this, and for similar links for waveform.
2017-05-23 23:51:26 -04:00
Andrew Johnson
c670ef0199 Merge 3.15 branch into master 2017-05-19 17:42:40 -05:00
Andrew Johnson
43ea188385 Merge 3.15 branch into 3.16
# Conflicts:
#	configure/CONFIG_BASE
#	configure/RULES_BUILD
2017-05-18 17:10:40 -05:00
Andrew Johnson
ffa7399c71 Merge changes from 3.15 branch 2017-05-11 16:39:52 -05:00
Ralph Lange
78b910574d ci/appveyor: print perl version to console log 2017-05-10 17:31:25 +02:00
Andrew Johnson
020f09e83a Fix EPICS_CA_AUTO_ARRAY_BYTES doc'n in CAref.html 2017-05-09 14:58:40 -05:00
Andrew Johnson
ac590e671e Adjustments to Checklist commands 2017-05-09 14:46:25 -05:00
Andrew Johnson
e0dea7ab23 Set snapshot to -rc1-DEV 2017-05-09 14:45:55 -05:00
Andrew Johnson
7aefee6737 Set Base version number for 3.16.1-rc1 2017-05-09 14:00:29 -05:00
Andrew Johnson
f9564a3b82 Various Release Notes tweaks 2017-05-09 13:57:17 -05:00
Andrew Johnson
17da4bfc1f Additional ReleaseChecklist updates 2017-05-09 13:08:59 -05:00
Ralph Lange
2fe8d82872 ci: make appveyor version number unambiguous 2017-05-09 14:03:40 +02:00
Ralph Lange
2ff9f249a0 ci: add appveyor configuration 2017-05-09 12:01:36 +02:00
Andrew Johnson
5ec1340902 Convert ReleaseChecklist commands to git 2017-05-08 20:45:39 -05:00
Michael Davidsaver
269f828733 ca: assume that CA name servers have minor version >=12
Assume that servers listed in EPICS_CA_NAME_SERVERS
support CA >=12, practically >=1 to support the
authentication messages.
2017-05-07 20:27:34 -04:00
Michael Davidsaver
4ce60c9797 src/tools: avoid dep. warning in rRDD generated
when building a support module
2017-05-07 20:27:34 -04:00
Michael Davidsaver
d5fc8c9b76 ioc/dbStatic: reduce warning spam for typed rset
There are an amazing number of warnings in any code which
includes recSup.h indirectly, including dbStaticLib.h.
Don't use the RECSUPFUN typedef internally to reduce
the number.
2017-05-07 10:06:38 -04:00
Andrew Johnson
93c0dcd3e5 Missing include 2017-05-06 01:11:53 -05:00
Andrew Johnson
fd583ac594 Fix MSC 2-digit-exponent in cvtFastTest.c 2017-05-06 00:41:52 -05:00
Michael Davidsaver
9621ff1552 libCom/test: cvtFastTest improve output 2017-05-05 20:54:19 -04:00
Michael Davidsaver
3f49787be1 ioc/db/test: fix jlinkz dllimport/export 2017-05-05 20:38:20 -04:00
Michael Davidsaver
bbd9ba0b6d std/filters: fix filters test harness 2017-05-05 20:15:03 -04:00
Michael Davidsaver
fcd443a026 missing test spec 2017-05-05 17:14:15 -04:00
Michael Davidsaver
02809de380 fix long long constants 2017-05-04 21:13:07 -04:00
Michael Davidsaver
987943be4e Merge remote-tracking branch 'int64b/master'
* int64b/master: (25 commits)
  std/rec: streamline variable names in int64in/int64out
  std/rec/test: recMiscTest check in64in/out
  ioc/db: dbUnitTest helps support int64
  std/rec: ioc64in/outRecord typed rset
  minor
  std/rec: fix copyright in int64in sources
  std: remove SCM keywords from int64in and int64out sources
  std/rec: fix promptgroups in dbd.pod files
  std/rec: add and improve pod for int64in and int64out
  std/rec: add pod documentation content for int64out
  std/rec: add pod documentation for int64out record
  dbStatic: dbPutStringNum() overflow handling
  dbStatic: more informative error for bad field value
  dbStatic: dbPutStringNum(, "") not an error
  Release Notes
  cvtFastPerform: Rename reserved member names, fix for vxWorks
  Simplify epicsConvertDoubleToFloat()
  More cvtFastPerform changes
  Collate and report by precision
  Restructure cvtFastPerform, fix VxWorks build
  ...
2017-05-04 20:18:24 -04:00
Michael Davidsaver
16a3657613 Merge remote-tracking branch 'linksup/master'
* linksup/master: (112 commits)
  ioc/dbStatic: rename link debugging info tags
  jlif future proof for 64-bit json parser
  Demonstrate and use numeric literals in calc args
  separate jlink and lset debug flags
  std/link: runtime conditional debugging in calc/const
  std/rec/test: extend linkRetargetLink w/ jlink
  ioc/db: dbUnitTest add testdbPutArrFieldOk()
  ioc/db: cleanup dbEvent freeLists
  ioc/db: dbUnitTest testMonitor leaks dbChannel
  std/link: all calc example
  jlink conditional debug print
  ioc/as: dbCore needs ca
  Additional linkInitTest checks
  Minimize work done in readLocked routine
  Minimize work done in readLocked() routine
  Cosmetic changes to various soft device supports
  Enhancements to subArray record & soft device support
  Fix bug in eventRecord::init_record
  Updates to Release Notes and links.html
  Make dbLinkIs{Constant|Volatile}() return only true/false
  ...

Conflicts:
	documentation/RELEASE_NOTES.html
	src/ioc/db/dbAccess.c
2017-05-04 20:14:30 -04:00
Michael Davidsaver
8ae7930375 ioc/dbStatic: rename link debugging info tags 2017-05-04 20:12:02 -04:00
Andrew Johnson
05d3e640cd Testing msi: Add retries if necessary
Hoping this will fix the annoying problems on Windows Jenkins.
2017-05-04 14:48:18 -05:00
Andrew Johnson
efe8d69f82 dbStaticTest: More friendly test output 2017-05-04 12:33:32 -05:00
Andrew Johnson
2c65739286 Change indfield settings in new dbInitEntryFrom*()
Can get indfield value from dbAddr->pflddes->indRecordType.
Make FromRecord set indfield=0 like dbFindRecord() does.

Adjust dbStaticTest to match.
2017-05-04 12:31:17 -05:00
Andrew Johnson
93fe387e87 Fix dbStaticTest recnode flags check 2017-05-04 12:23:57 -05:00
Ralph Lange
ad0695b119 std/rec: streamline variable names in int64in/int64out 2017-05-04 09:27:23 +02:00
Michael Davidsaver
8f880a614c ioc/db/test: check record node flags 2017-05-03 19:32:50 -04:00
Michael Davidsaver
7805fbe295 ioc/dbStatic: rename dbRecordNode aliasedRecord -> aliasedRecnode 2017-05-03 19:31:38 -04:00
Michael Davidsaver
2a81e0b338 std/rec/test: recMiscTest check in64in/out 2017-05-03 19:18:52 -04:00
Michael Davidsaver
5e0dc5d1c9 ioc/db: dbUnitTest helps support int64 2017-05-03 18:39:43 -04:00
Michael Davidsaver
1b16c7130b std/rec: ioc64in/outRecord typed rset 2017-05-03 17:58:29 -04:00
Michael Davidsaver
925d03bcec minor 2017-05-03 17:54:58 -04:00
Michael Davidsaver
1151d78cb5 Merge remote-tracking branch 'launchpad/master'
* launchpad/master: (116 commits)
  ioc/rsrv: bounds check DBR
  CAref mention EPICS_CA_MCAST_TTL
  EPICS_CA_AUTO_MAX_ARRAY_BYTES -> EPICS_CA_AUTO_ARRAY_BYTES
  missing include
  ioc/db/test: dbStaticTest dbInitEntryFromAddr() works before iocInit()
  ioc/db/test: dbStaticTest test operations on aliases
  ioc: rename dbCommonPvt::recnode
  ioc/dbStatic: better alias tracking
  ioc/dbStatic: add dbInitEntryFromRecord()
  ioc: populate RDES early
  rename dbInitEntryFromChannel -> dbInitEntryFromAddr
  ioc/db: Add dbCommonPvt
  ioc/dbStatic: add dbInitEntryFromChannel()
  ioc/dbStatic: dbAllocRecord whitespace
  ioc/rsrv: fix C89 issue
  add EPICS_CA_MCAST_TTL
  update RELEASE_NOTES
  replace caLimitArray with EPICS_CA_AUTO_MAX_ARRAY_BYTES
  update RELEASE_NOTES
  rename iocshFind -> iocshFindCommand
  ...

Conflicts:
	documentation/RELEASE_NOTES.html
	src/ioc/db/dbConvert.c
	src/ioc/db/dbFastLinkConv.c
	src/ioc/db/test/Makefile
	src/ioc/db/test/dbPutGetTest.c
	src/ioc/db/test/dbPutGetTest.db
	src/ioc/dbStatic/dbStaticRun.c
2017-05-03 17:54:43 -04:00
Michael Davidsaver
b4c625d8d1 jlif future proof for 64-bit json parser 2017-05-03 17:27:57 -04:00
Michael Davidsaver
096fb5e0a2 Merge remote-tracking branch 'addr2entry/master'
* addr2entry/master:
  ioc/db/test: dbStaticTest dbInitEntryFromAddr() works before iocInit()
  ioc/db/test: dbStaticTest test operations on aliases
  ioc: rename dbCommonPvt::recnode
  ioc/dbStatic: better alias tracking
  ioc/dbStatic: add dbInitEntryFromRecord()
  ioc: populate RDES early
  rename dbInitEntryFromChannel -> dbInitEntryFromAddr
  ioc/db: Add dbCommonPvt
  ioc/dbStatic: add dbInitEntryFromChannel()
  ioc/dbStatic: dbAllocRecord whitespace
2017-05-03 17:07:07 -04:00
Michael Davidsaver
8640e1c9fb Merge remote-tracking branch 'launchpad/3.15'
* launchpad/3.15:
  ioc/rsrv: bounds check DBR
2017-05-03 17:06:51 -04:00
Michael Davidsaver
d154d8eab7 CAref mention EPICS_CA_MCAST_TTL 2017-05-03 14:17:56 -04:00
Michael Davidsaver
3fbdcdb032 EPICS_CA_AUTO_MAX_ARRAY_BYTES -> EPICS_CA_AUTO_ARRAY_BYTES 2017-05-03 13:59:35 -04:00
Ralph Lange
eedf296cd2 std/rec: fix copyright in int64in sources 2017-05-03 17:07:46 +02:00
Ralph Lange
f0d7d42ab4 std: remove SCM keywords from int64in and int64out sources 2017-05-03 17:07:06 +02:00
Ralph Lange
5761028d6f std/rec: fix promptgroups in dbd.pod files 2017-05-03 17:00:19 +02:00
Michael Davidsaver
fbc1ed26f0 missing include 2017-05-03 10:18:32 -04:00
Ralph Lange
93b47f103e std/rec: add and improve pod for int64in and int64out 2017-05-03 16:17:27 +02:00
Michael Davidsaver
1917d0563a ioc/db/test: dbStaticTest dbInitEntryFromAddr() works before iocInit() 2017-05-02 21:30:43 -04:00
Michael Davidsaver
da4bf2d5ee ioc/db/test: dbStaticTest test operations on aliases 2017-05-02 21:12:09 -04:00
Michael Davidsaver
ec3a89e43c ioc: rename dbCommonPvt::recnode 2017-05-02 21:11:46 -04:00
Michael Davidsaver
62475a383e ioc/dbStatic: better alias tracking
Ensure that alias of alias sets DBRN_FLAGS_HASALIAS
on the aliased dbRecordNode.

Add dbFollowAlias() for completeness.
2017-05-02 21:11:46 -04:00
Michael Davidsaver
6ba949cdb4 ioc/dbStatic: add dbInitEntryFromRecord() 2017-05-02 21:11:46 -04:00
Michael Davidsaver
5d37bc2996 ioc: populate RDES early
The record type is known at allocation time,
so store RDES immediately.
2017-05-02 21:11:46 -04:00
Michael Davidsaver
2eaede9925 rename dbInitEntryFromChannel -> dbInitEntryFromAddr 2017-05-02 21:11:46 -04:00
Michael Davidsaver
12d68e6021 ioc/db: Add dbCommonPvt
Add some hidden "fields" for every record.
Allows Base internal hidden accounting
which can be changed without an ABI break.
2017-05-02 21:11:46 -04:00
Michael Davidsaver
78a7ad168e ioc/dbStatic: add dbInitEntryFromChannel()
Constant time population of a DBENTRY from
a valid dbAddr.
2017-05-02 21:11:46 -04:00
Michael Davidsaver
f716b1b26a ioc/dbStatic: dbAllocRecord whitespace 2017-05-02 21:11:46 -04:00
Michael Davidsaver
0bbb381efd ioc/rsrv: fix C89 issue 2017-05-02 21:06:35 -04:00
Michael Davidsaver
f2a1834dc9 add EPICS_CA_MCAST_TTL
may be necessary/helpful for mcast search/beacon usage
across sub-nets.
2017-05-02 20:35:00 -04:00
Michael Davidsaver
6572816a6a update RELEASE_NOTES 2017-05-02 20:16:49 -04:00
Michael Davidsaver
c304e29da6 Merge remote-tracking branch 'cahuge/master'
* cahuge/master:
  replace caLimitArray with EPICS_CA_AUTO_MAX_ARRAY_BYTES
  ca: fix export caLimitArray on win32
  rsrv: export variable caLimitArray
  rsrv: optional max_array_bytes
  cas: simplify buffer alloc
  ca: large array free list is optional
  rsrv: support larger than max. array bytes
  pcas: support larger than max array bytes
  ca: support alloc larger than max array bytes
2017-05-02 20:06:54 -04:00
Michael Davidsaver
9fd8eec2e2 replace caLimitArray with EPICS_CA_AUTO_MAX_ARRAY_BYTES 2017-05-02 19:31:21 -04:00
Michael Davidsaver
a873c4f3dc Merge remote-tracking branch 'launchpad/3.15'
* launchpad/3.15:
  rename iocshFind -> iocshFindCommand
  Added patch
  Changed function outputs to remove pointer to next function.
  more whitespace
  whitespace
  Added functions to allow access to what functions and variables the ioc shell has registered.
  missing include
  ioc/dbStatic: dbFreeBase() don't double free alias'd records
  ioc/dbStatic: plug leak in dbFreeBase()
  ioc/dbStatic: whitespace
  Fix indentation warning from GCC
  libCom/test: errlog test more verbose
  libCom: STATIC_ASSERT use c++11 static_assert when possible
  Check for empty PV names in Perl catools

Conflicts:
	src/std/rec/subRecord.c
2017-05-02 19:08:51 -04:00
Michael Davidsaver
26650d6cbf update RELEASE_NOTES 2017-05-02 19:02:18 -04:00
Michael Davidsaver
d1a0b74c83 Merge remote-tracking branch 'camodern/master'
* camodern/master:
  cas: ignore CA client version older than v4.4
  rsrv: remove !CA_V44() code
  rsrv: no ca exception response to UDP
  rsrv: ignore CA client version older than v4.4
  cas: honor DOREPLY for TCP searches
  cas: ignore echo and unexpected UDP
  rsrv: send channel create failure
  rsrv: UDP search ignore DOREPLY
  rsrv: ignore echo and unexpected UDP

Conflicts:
	src/ca/legacy/pcas/generic/casDGClient.cc
2017-05-02 18:41:09 -04:00
Andrew Johnson
83428d2b2c db/test: Cleanup unused variable 2017-05-02 12:39:09 -05:00
Ralph Lange
1235ad76e7 std/rec: add pod documentation content for int64out 2017-05-02 13:51:44 +02:00
Andrew Johnson
1cad1c5ba6 Demonstrate and use numeric literals in calc args 2017-04-29 20:43:54 -05:00
Michael Davidsaver
12fc7ed07c libCom: add EPICS_FUNCTION
Automatic macro which expands to the current function name.
Useful in debug prints.
2017-04-28 19:19:14 -04:00
Michael Davidsaver
564ef01951 typo 2017-04-28 19:19:14 -04:00
Michael Davidsaver
f65b2119ad separate jlink and lset debug flags
"lsetDebug" for lset callbacks and "jlinkDebug" for jlink parsing.
2017-04-28 17:11:47 -04:00
Michael Davidsaver
4a9fe82575 std/link: runtime conditional debugging in calc/const 2017-04-28 16:59:26 -04:00
Michael Davidsaver
2a1f790909 std/rec/test: extend linkRetargetLink w/ jlink 2017-04-28 16:59:26 -04:00
Michael Davidsaver
d752b962d5 ioc/db: dbUnitTest add testdbPutArrFieldOk() 2017-04-28 16:44:18 -04:00
Michael Davidsaver
b4db176e48 ioc/db: cleanup dbEvent freeLists 2017-04-28 15:47:27 -04:00
Michael Davidsaver
d397f0fd92 ioc/db: dbUnitTest testMonitor leaks dbChannel 2017-04-28 15:43:17 -04:00
Ralph Lange
b096dc3e01 std/rec: add pod documentation for int64out record 2017-04-28 16:41:02 +02:00
Michael Davidsaver
be8de34130 std/link: all calc example 2017-04-27 19:50:46 -04:00
Michael Davidsaver
579a0791ea jlink conditional debug print
Enable magic info("linkDebug","YES") to enable
debug prints during parsing.
2017-04-27 19:46:33 -04:00
Michael Davidsaver
e51cc39b0c ioc/as: dbCore needs ca 2017-04-27 17:24:23 -04:00
Michael Davidsaver
e296e99667 Merge remote-tracking branch 'launchpad/master'
* launchpad/master:
  libCom: dbmfMalloc cantProeed() on failure
  ioc/db/test: dbCaLinkTest fix sync
  oops
  std/filter/test: use dbUnitTest
  travis-ci enable mingw w/ dll
  travisci
  catools: Fix SEGFAULT from bad PV names
  typo
  Fix for dbCa warning seg-fault
  Fix postfix.h macro arg, document
  libCom/test: epicsCalcTest use exact postifx buffers

Conflicts:
	src/ioc/db/test/dbCaLinkTest.c
2017-04-27 17:17:29 -04:00
Michael Davidsaver
8677c84528 libCom: dbmfMalloc cantProeed() on failure
most calling code doesn't check for NULL.
2017-04-27 15:30:35 -04:00
Michael Davidsaver
052573f4ca ioc/db/test: dbCaLinkTest fix sync 2017-04-27 15:14:58 -04:00
Michael Davidsaver
7a727bbd41 Merge remote-tracking branch 'launchpad/3.15'
* launchpad/3.15:
  oops
  std/filter/test: use dbUnitTest
  travis-ci enable mingw w/ dll
  travisci
  catools: Fix SEGFAULT from bad PV names
  typo
  Fix for dbCa warning seg-fault
  Fix postfix.h macro arg, document
  libCom/test: epicsCalcTest use exact postifx buffers
2017-04-27 14:31:53 -04:00
Andrew Johnson
0748adfb9a Additional linkInitTest checks
Now tests array record types and the eventRecord.
Also moved repeated IOC startup code into separate function.
2017-04-26 16:04:13 -05:00
Andrew Johnson
4813b37538 Minimize work done in readLocked routine
Move post-I/O back to read_event.
Fix initialization bug.
2017-04-26 16:01:09 -05:00
Andrew Johnson
bbd94928bb Minimize work done in readLocked() routine
Move post-I/O work back to the read_xx routines.
2017-04-26 15:59:03 -05:00
Andrew Johnson
c13a4f24ce Cosmetic changes to various soft device supports 2017-04-26 15:55:03 -05:00
Andrew Johnson
d1af663705 Enhancements to subArray record & soft device support
Permit record's use as a look-up-table by reading constant
input array data in dset::read_sa() routine.

Move sub-array operation into a separate function.
Extract subarray from constant INP value at device init.
Reduce the work done inside readLocked() to a minimum.
Limit NELM value to at most MALM in record init routine.
2017-04-26 15:52:08 -05:00
Andrew Johnson
4eafb6fd8e Fix bug in eventRecord::init_record
Look up event handle /after/ the device init routine has been run,
in case it modified the event name in VAL. That didn't used to
be possible because constant links couldn't return strings.
2017-04-26 15:03:43 -05:00
Andrew Johnson
33f3145fcc Updates to Release Notes and links.html 2017-04-25 22:52:08 -05:00
Andrew Johnson
c71afb631c Make dbLinkIs{Constant|Volatile}() return only true/false 2017-04-25 20:37:09 -05:00
Andrew Johnson
da94b7a2e4 Fix dbConstLink to handle a long-string array properly
Added a new parser dbLSConvertJSON for long-string arrays.
New test checks that only the first string element is used.
2017-04-24 17:09:01 -05:00
Andrew Johnson
311ad57e93 printfRecord: Handle const long-strings in "%ls"
Adds some tests for printfRecord.
2017-04-24 15:18:52 -05:00
Andrew Johnson
30e634b97b Adjust calcout's handling of undefined links 2017-04-23 23:32:15 -05:00
Andrew Johnson
421a2c8eb9 Tidy up lnkConst.c after Michael's bug-fix changes
Should make the code easier to follow.
2017-04-23 00:11:22 -05:00
Michael Davidsaver
cfe9a51c5d std/rec/test: start linkInitTest 2017-04-21 17:26:58 -04:00
Michael Davidsaver
066984e11d Merge branch 'master' into link
* master: (226 commits)
  ioc/db: testdbGetFieldEqual() detect zero size
  Cleanup in asLib
  Allow whitespace before comments in AS config files
  Supress MS warning C4251
  Add a plan to std/filters/test/syncTest.c
  Fix dbUnitTest.c
  avoid void* +=
  Fix and test for macLib losing error status
  update notes
  libCom/test: ipAddrToAsciiTest skip cleanup unless valgrind is possible
  libCom/test: add ipAddrToAsciiTest to testHarness
  db/test: dbPutGetTest check dbGet() of long string field
  db: dbGet() ensure long string nil and actual string length
  db/test: dbPutGetTest check for dbGet() attribute crash
  db: fix dbGet() for attributes as long string
  db/test: dbPutGetTest add test for lp:1678494
  db: fix dbGet() of link fields as DBF_CHAR
  dbUnitTest: add testdbGetArrFieldEqual()
  db/test: add dbPutGetTest
  Update release notes as per Michael's review comment
  ...

Conflicts:
	src/ioc/db/dbLink.c
	src/ioc/db/test/Makefile
	src/std/dev/devSoSoftCallback.c
	src/std/rec/boRecord.c
	src/std/rec/dfanoutRecord.c
	src/std/rec/longinRecord.c
	src/std/rec/longoutRecord.c
2017-04-21 17:20:12 -04:00
Michael Davidsaver
6c062981fb Merge remote-tracking branch 'launchpad/3.15'
* launchpad/3.15:
  ioc/db: testdbGetFieldEqual() detect zero size
  Cleanup in asLib
  Allow whitespace before comments in AS config files
  Supress MS warning C4251
  Add a plan to std/filters/test/syncTest.c
  Fix dbUnitTest.c
  avoid void* +=
  Fix and test for macLib losing error status
  update notes
  libCom/test: ipAddrToAsciiTest skip cleanup unless valgrind is possible
  libCom/test: add ipAddrToAsciiTest to testHarness
  Adjusted .gitignore patterns
  libCom/test: add network libraries for Windows builds
  Moved .bzrignore to .gitignore
  libCom/test: add ipAddrToAsciiTest
  libCom: revise ipAddrToAscii
2017-04-21 16:16:03 -04:00
Michael Davidsaver
54e94a1e12 std/link: lnkConst refactor
Avoid variable with same name as typedef.
Confuses qtcreator.
2017-04-21 16:08:48 -04:00
Michael Davidsaver
414e5b82b8 std/link: lnkCalc require expression
error if 'expr' key isn't provided.
2017-04-21 16:08:33 -04:00
Michael Davidsaver
b99a7b9252 std/link: lnkConst fix mem leak and hard fail on no mem 2017-04-21 16:08:15 -04:00
Michael Davidsaver
43f6a06bcd std/link: lnkConst avoid cantProceed() 2017-04-21 16:08:10 -04:00
Michael Davidsaver
7121b016d5 ioc/db: dbConstLoadLS handle size=0
handle size=0 and clarify
2017-04-21 16:08:04 -04:00
Michael Davidsaver
8b24383e9e arrayOpTest: check initial dbGet value 2017-04-21 16:07:55 -04:00
Andrew Johnson
e99fe61e07 Fix postfix.h macro arg and document 2017-04-21 14:18:05 -05:00
Andrew Johnson
23cef0339e Fix buffer allocation bug in lnkCalc.c 2017-04-21 13:56:49 -05:00
Andrew Johnson
611cb3f52e Fix typos, remove FIXMEs from lnkConst.c 2017-04-21 13:55:59 -05:00
Andrew Johnson
7e60faae10 No need to truncate const string array elements 2017-04-21 13:04:53 -05:00
Michael Davidsaver
4f1b244589 ca: fix export caLimitArray on win32 2017-04-20 09:54:05 -04:00
Andrew Johnson
dcb1f75b4d Cosmetic cleanups 2017-04-19 16:53:12 -05:00
Andrew Johnson
89f13aa51b Modify soft devices to synchronize TSEL=-2 timestamps
Use dbLinkDoLocked() to ensure a timestamp set by TSEL=-2
comes from the same update as the value.
2017-04-19 16:50:38 -05:00
Andrew Johnson
d2db634ed2 Add dbLinkDoLocked() support
New lset method, implemented in all link types.
Includes a test for the dbCa implementation.
2017-04-19 16:44:11 -05:00
Michael Davidsaver
6bf66d1c93 Merge remote-tracking branch 'launchpad/3.15'
* launchpad/3.15:
  db/test: dbPutGetTest check dbGet() of long string field
  db: dbGet() ensure long string nil and actual string length
  db/test: dbPutGetTest check for dbGet() attribute crash
  db: fix dbGet() for attributes as long string
  db/test: dbPutGetTest add test for lp:1678494
  db: fix dbGet() of link fields as DBF_CHAR
  dbUnitTest: add testdbGetArrFieldEqual()
  db/test: add dbPutGetTest
  Adjusted .gitignore patterns
  Move .bzrignore to .gitignore
2017-04-06 20:32:48 -04:00
Ralph Lange
865a870912 Merged typed-recsup branch (by Ben / Ralph) 2017-04-05 09:42:16 +02:00
Ralph Lange
9bfc8d8fad Update release notes as per Michael's review comment 2017-04-03 09:55:06 +02:00
Andrew Johnson
23a856ae9b Adjusted .gitignore patterns 2017-03-31 12:22:29 -05:00
Ralph Lange
6884e0ce61 Moved .bzrignore to .gitignore 2017-03-30 17:08:29 +02:00
Ralph Lange
9e778511ee Add opt-in switch to makeBaseApp example 2017-03-30 16:35:54 +02:00
Ralph Lange
bad1b0ead3 Update release notes with opt-in instructions 2017-03-30 16:26:54 +02:00
Ralph Lange
ecf5ab4a4c Deprecate RECSUPFUN and the untyped struct rset. 2017-03-30 16:14:09 +02:00
Ralph Lange
2f510af603 Use (typed) rset instead of (untyped) struct rset inside Base 2017-03-30 14:35:24 +02:00
Ralph Lange
0f2e26bc4c Make generated code always use typed_rset
always cast to cover old-style supports
2017-03-30 14:33:06 +02:00
Ralph Lange
26a4e1489f Make compilation inside Base USE_TYPED_RSET 2017-03-30 14:30:53 +02:00
Ralph Lange
19be96ec3a Add opt-in switch USE_TYPED_RSET 2017-03-30 14:28:48 +02:00
Ralph Lange
6397204354 Update release notes, C++ instructions are tested 2017-03-27 09:51:32 +02:00
Ralph Lange
89a858f655 Remove remaining REC_TYPE defines 2017-03-27 09:49:30 +02:00
Ralph Lange
0b410c1b03 Update release notes entry 2017-03-24 17:16:18 +01:00
Ralph Lange
4f8134c63c Fix xxxRecord in templates to make exampleApp work 2017-03-24 17:08:07 +01:00
Ralph Lange
ef2da59c24 Remove REC_TYPE and UNTYPED_RSET/oldRecSup.h; add casts to record types 2017-03-24 17:07:22 +01:00
Ben Franksen
40c9e4799b use new typed rset only if UNTYPED_RSET is not defined, adapted release notes
Also moved the old definition(s) to a separate header file named oldRecSup.h
to avoid cluttering the new header file.
2017-03-21 17:01:13 +01:00
Michael Davidsaver
675c2aff14 rsrv: export variable caLimitArray 2017-03-18 17:41:33 -04:00
Michael Davidsaver
1636f3d9fe rsrv: optional max_array_bytes
use of large array free list is optional
2017-03-18 17:41:33 -04:00
Michael Davidsaver
1e7c80c909 cas: simplify buffer alloc
eliminate casBufferFactory.
move small buffer free list into clientBufMemoryManager
2017-03-18 17:41:33 -04:00
Michael Davidsaver
2096c60652 ca: large array free list is optional 2017-03-18 17:41:33 -04:00
Michael Davidsaver
3009f88f64 rsrv: support larger than max. array bytes 2017-03-13 19:22:56 -04:00
Michael Davidsaver
b783427bf7 pcas: support larger than max array bytes
clientBufMemoryManager already supports allocations
larger than max array bytes, adjust callers inBuf/outBuf
to actually request larger allocations.
2017-03-13 19:22:53 -04:00
Michael Davidsaver
85b6b5c507 ca: support alloc larger than max array bytes
automatically try to allocate a custom buffer
when a message larger than ca max array bytes
is encountered.
2017-03-13 19:22:50 -04:00
Andrew Johnson
20627c0465 Merged changes from 3.15 branch to revno 12809 2017-03-08 10:36:41 -06:00
Andrew Johnson
17bd1ae6d0 db/test: Fix warning from clang 2017-03-03 12:23:36 -06:00
Ben Franksen
f71fe62bc3 added release notes entry 2017-03-03 17:40:24 +01:00
Ben Franksen
825c075df7 fixes in recSup and record types according to merge review
* removed struct valueDes
* made get_value take void (no arguments), added deprecation note
* removed misleading array size comment for get_units

Also added const to method parameters exactly where called in base with
const arguments.
2017-03-03 16:43:50 +01:00
Ben Franksen
ff91ede462 revert use of struct dbr_precision in call to get_precision in dbAccess.c 2017-03-03 16:41:03 +01:00
Michael Davidsaver
1d749ac7e7 dbLock: add assert in dbScanLock
catch locking attempts before iocInit()
2017-02-28 21:00:57 -06:00
Michael Davidsaver
6377c2e1e4 db/test: dbPutLinkTest include json links and more 2017-02-28 20:58:11 -06:00
Andrew Johnson
8069d9d80b dbUnitTest: Improve output slightly 2017-02-28 20:55:05 -06:00
Michael Davidsaver
46993a5e38 dbUnitTest: more informative dbPutField*() 2017-02-28 20:09:21 -06:00
Michael Davidsaver
2bb02e732a libCom: add errSymMsg() error message lookup
Like errSymLookup() but always returns a static string.
2017-02-28 20:06:42 -06:00
Michael Davidsaver
428dfe7a5c add testing lset 2017-02-28 18:00:51 -06:00
Andrew Johnson
5dcd3483ba dbStatic: dbPutStringNum() overflow handling
Default to accepting over-size integers in DB fields, truncate to field size.
E.g. permits setting DBF_LONG fields to 0xffffffff.
Adds dbConvertStrict config variable to disable this.
2017-02-28 00:25:43 -06:00
Ben Franksen
1c3ffa1c76 fixed the wrong fix for getOptions in dbAccess.h 2017-02-26 13:54:58 +01:00
Ben Franksen
cc946b760c partly fix lp:1666924, i.e. for rset only, as described in the ticket
This means:

* typed method definitions for struct rset
* using REC_TYPE macro in place of dbCommon
* define REC_TYPE as dbCommon unless defined
* in record supports, define REC_TYPE before including epics headers
* fix a few method types in record supports (e.g. void* -> REC_TYPE*)
* fix the type errors gcc finds in dbAccess.c and dbConvert.c
2017-02-24 21:11:11 +01:00
Andrew Johnson
00549c832a Fix HTML entities 2017-02-17 14:16:57 -06:00
Andrew Johnson
c52088205e Remove constant link checks from test device 2017-02-17 14:15:31 -06:00
Andrew Johnson
e95fcb2e06 Merged changes from 3.15 branch, to revno 12807 2017-02-01 11:57:04 -06:00
Andrew Johnson
a7f0525ac7 Update Release Checklist 2017-01-30 18:04:47 -06:00
Andrew Johnson
051c059938 Removed some Revision-Id keywords 2017-01-06 17:31:51 -06:00
Andrew Johnson
fab5ce675f Update comments in calcoutRecord 2016-12-12 17:44:01 -06:00
Andrew Johnson
0a4981093a Update mingw32 cross-target name for RHEL7 2016-11-15 17:44:21 -06:00
Michael Davidsaver
99500b9be4 dbStatic: more informative error for bad field value 2016-09-18 17:35:19 -04:00
Michael Davidsaver
0821c8c4ff dbStatic: dbPutStringNum(, "") not an error
Restore previous behavour that empty string
is equivalent to numeric zero.

epicsParse*() returns S_stdlib_noConversion
where previously strtoul() did not.

Conflicts:
	src/ioc/db/test/Makefile
2016-09-12 18:20:02 -04:00
Andrew Johnson
da5455ed22 Fixes for Windows builds 2016-09-09 11:14:59 -05:00
Andrew Johnson
58c78af4f9 Initialize all fields of jlink, link types may not use calloc 2016-09-07 23:35:39 -05:00
Andrew Johnson
813166128e Merged changes from 3.15 branch, to revno 12781 2016-09-07 10:04:54 -05:00
Andrew Johnson
b2012fdfb5 Added test link type, fix dbPutLinkTest for JSON_LINKs 2016-09-07 00:50:40 -05:00
Andrew Johnson
c12a35e388 Clean up memory leaks 2016-09-07 00:47:51 -05:00
Andrew Johnson
8a9707e74f Fixed a small memory leak in lnkCalc 2016-09-06 22:28:36 -05:00
Andrew Johnson
2d4301f0bb Fix warnings from clang 2016-09-05 22:36:45 -05:00
Andrew Johnson
268e59b052 Minor updates 2016-09-05 15:38:16 -05:00
Andrew Johnson
5b74799605 Some documentation updates 2016-09-05 15:12:09 -05:00
Andrew Johnson
cd49e245c2 Added JLink reporting infrastructure
Command 'dbjlr <record|*> <level>' calls the report method for
all JSON links in all records, or in one named record.
Added level and indent arguments to the jlif::report() method.

Added jlif::map_children() method for recursing through all
JSON links, plus dbJLinkMapChildren() and dbJLinkMapAll() APIs.

Implemented the report and map_children methods in the const
and calc link types.
2016-09-05 14:25:33 -05:00
Andrew Johnson
19447dc7ff Make the long-string buffer for link fields bigger
When representing a link field as a long string (.INP$)
we have to pick some size limit for the buffer.
Previously this was the max length of a PV name + 12 chars,
but with JSON links that's not big enough.

This commit sets it to 1KB and defines a macro so it will be
easier to change in the future if necessary.
2016-09-04 16:56:15 -05:00
Andrew Johnson
dd311be319 JLink: Convert parser->linkDepth into jlink->parseDepth
This counter is indicates when we've finished parsing a link,
and needs to be stored with link rather than the parser so it
keeps its value while parsing embedded links. This fixes the
embedded links bug.

Also removed the limit on a link name's length.
2016-09-04 16:33:10 -05:00
Andrew Johnson
4448317d73 Add lnkConst_remove, fix debug messages 2016-09-04 16:02:59 -05:00
Andrew Johnson
ec6d86c91c Fix jlink memory leak in dbStaticLib
Added dbFreeLinkInfo(), use everywhere to release dbLinkInfo resources.

Renamed link_type => expected_type in db[Can]SetLink(),
my brain understands this name faster.
2016-09-04 15:56:39 -05:00
Andrew Johnson
4302da3628 Minor fixes to the calc link-type 2016-09-03 22:24:55 -05:00
Andrew Johnson
25315882ec Clean up JSON_LINKs in doCloseLinks 2016-09-03 22:22:12 -05:00
Andrew Johnson
f8d6cd98a0 Minor cleanups 2016-09-03 19:44:49 -05:00
Andrew Johnson
5fe3e8bfb5 Added calc link-type 2016-09-03 19:22:55 -05:00
Andrew Johnson
8d1c416551 Moved PV_LINK-specific code out of dbLink.c into link types
This required a change to the lset::getValue arguments, removing
the pstat and psevr pointers. Links can still return a non-zero
value from getValue and trigger a LINK:INVALID alarm, but for any
other alarm settings they must manipulate the record themselves.
2016-09-03 19:21:11 -05:00
Andrew Johnson
07b09eed1f Fixes to dbJLink, added dbJLinkFree()
Moved the clearing of key_is_link to the right place,
embedded links now parse correctly.
2016-09-03 13:36:17 -05:00
Andrew Johnson
1e1c52cb69 Use new epicsStrnDup() API 2016-09-03 13:27:30 -05:00
Andrew Johnson
6e88d48615 Added epicsStrnDup() and dbmfStrndup() routines
The JSON parser passes string arguments with a length
instead or nil-terminating them. These routines make it
simple to copy such strings into either permanent or
temporary storage.
2016-09-03 13:25:19 -05:00
Andrew Johnson
23c71e9965 Various improvements
* Added new lset::openLink() method, called on JSON_LINKs only
* Cleanup in dbJLink.c to prevent memory leaks.
* Removed jlif::start_parse() method.
* Renamed jlif::end_parse() to end_child, which will be called on
the parent link when a child link has succesfully finished parsing.
2016-09-01 23:21:23 -05:00
Andrew Johnson
3992d4b92a Split dbJLinkInit, JLinks are now parsed at load-time 2016-09-01 00:56:26 -05:00
Andrew Johnson
40a3a66745 Added loadLS routine to lset
The long string in/out records use a different initializer
for constant links. The new loadLS method allows a constant
link type to initialize such a long string field.

NB: This routine was added in the middle of the lset table.
Any external link support implementations must be adjusted.
2016-08-31 00:36:23 -05:00
Andrew Johnson
d0dcd61b23 Add code for arrays of strings 2016-08-30 23:03:08 -05:00
Andrew Johnson
5ec0633282 Pass link dbfType to jlif allocator; needed! 2016-08-30 01:13:15 -05:00
Andrew Johnson
33e565b67d Fix build warning from clang 2016-08-29 10:41:51 -05:00
Andrew Johnson
7edc0c67ca JSON Links implementation
The lnkConst.c implementation is not yet complete, no support for arrays of
strings (JMOP).

Link error messages should display their record & field name, which is not yet
possible.

The ability to embed links as parameters to other link types is not complete
yet; this will be required for the calc link type.

This code currently passes all existing tests, but additional tests are needed
for the new functionality.
2016-08-29 01:12:09 -05:00
Andrew Johnson
056edc0d8a Undo buggy change 2016-08-28 23:41:35 -05:00
Andrew Johnson
fc66793ee2 Start documenting changes 2016-08-27 16:31:49 -05:00
Andrew Johnson
37b6cbb50c Use new dbLink APIs instead of checking link.type 2016-08-27 16:30:48 -05:00
Andrew Johnson
cca6a5d05a Add isConstant and isVolatile to LSET 2016-08-27 16:26:55 -05:00
Andrew Johnson
82385c9f1b Missed a spot handling JSON_LINK field values 2016-08-18 00:18:41 -05:00
Andrew Johnson
cbc7af0ef8 Remove 2 obsolete dbStatic routines (forms) 2016-08-15 20:19:19 -05:00
Andrew Johnson
bed1c618a8 Use dbPutLinkAsync() in all output SoftCallback dev's 2016-08-13 21:53:31 -05:00
Andrew Johnson
7df97f074e Add lset::dbPutLinkAsync and S_db_noLSET 2016-08-13 21:42:23 -05:00
Andrew Johnson
fe71fc98b8 Undo a small & unnecessary behaviour change 2016-08-12 23:53:42 -05:00
Andrew Johnson
d3a9ba7701 Fix issues related to const array initialization 2016-08-12 23:21:26 -05:00
Andrew Johnson
bb58598eba A cleaner way to close CA & DB links 2016-08-12 23:20:24 -05:00
Michael Davidsaver
899feb24b2 iocInit: close CA_LINKs through lset 2016-08-12 19:50:17 -04:00
Andrew Johnson
fb785e45c7 Adjust record and device support for array constants 2016-08-10 12:53:39 -05:00
Andrew Johnson
519208833f Add lset::loadArray and JSON parsing
Replace lset::loadLink with lset::loadScalar, add lset::loadArray
Add dbLoadLinkArray() routine to dbLink.h API
New dbConvertJSON.h API for use by dbConstLoadArray()
2016-08-10 12:49:49 -05:00
Andrew Johnson
ae2180f5b5 Comments in Makefile 2016-08-10 12:21:03 -05:00
Andrew Johnson
dafe2a83a3 libCom: Make yajl_alloc.h usable 2016-08-10 12:19:53 -05:00
Michael Davidsaver
ebfaca8228 cas: ignore CA client version older than v4.4
CAS ignore search and version messages
from CA minor versions older than 4.4.
2016-07-30 11:45:42 -04:00
Michael Davidsaver
da78e01e89 rsrv: remove !CA_V44() code
Remove code supporting deprecated
CA minor versions < 3
2016-07-31 19:49:08 -04:00
Michael Davidsaver
caf70216d3 rsrv: no ca exception response to UDP 2016-07-31 19:35:25 -04:00
Michael Davidsaver
95fd255dd6 rsrv: ignore CA client version older than v4.4
RSRV ignore search and version messages
from CA minor versions older than 4.
2016-07-30 10:35:49 -04:00
Michael Davidsaver
2dd16f4362 cas: honor DOREPLY for TCP searches 2016-07-31 15:10:36 -04:00
Michael Davidsaver
4c2b8819cd cas: ignore echo and unexpected UDP
Ignore UDP echo.
By default, don't log unexpected/invalid
UDP messages.
2016-07-30 11:46:28 -04:00
Michael Davidsaver
8992d5a593 rsrv: send channel create failure 2016-07-30 12:09:33 -04:00
Michael Davidsaver
802f29df47 rsrv: UDP search ignore DOREPLY
Don't send notice of failure
for lookup via. UDP.
2016-07-30 10:46:21 -04:00
Michael Davidsaver
16c419350b rsrv: ignore echo and unexpected UDP
Ignore UDP echo.
By default, don't log unexpected/invalid
UDP messages.
2016-07-30 10:41:39 -04:00
Andrew Johnson
935ab02bc1 Fix build failure on Solaris 2016-06-07 12:31:15 -05:00
Andrew Johnson
63d8651474 Make Perl DB parser handle duplicates and rtyp '*' 2016-06-07 01:00:38 -05:00
Andrew Johnson
c01967d64f Remove spurious include dbCa.h 2016-06-02 22:29:45 -05:00
Andrew Johnson
d1986edd9e Simplify link-type checks in record supports 2016-06-02 22:22:11 -05:00
Andrew Johnson
7627454f63 Simplify link-type checks in soft device supports 2016-06-02 22:02:54 -05:00
Andrew Johnson
667f74759d Allow (discard) comments inside JSON 2016-06-01 15:46:24 -05:00
Andrew Johnson
1f726c8760 Recognize arrays as constant links 2016-05-24 12:01:38 +02:00
Andrew Johnson
08b7802009 Recognize numbers before barewords 2016-05-24 11:59:08 +02:00
Andrew Johnson
f6c4099634 Make info tags also JSON objects 2016-05-23 12:00:11 +02:00
Andrew Johnson
c76041b14c Rename JSON_STR to JSON_LINK 2016-05-20 20:32:39 -05:00
Andrew Johnson
7ea544673a Accept bareword JSON strings, quote them 2016-05-20 00:02:45 -05:00
Andrew Johnson
6e6ae4354b Fix warnings from dbmfStrdup() change 2016-05-19 14:01:05 -05:00
Andrew Johnson
61e82ee1ae Fix memory allocation bugs 2016-05-19 01:32:12 -05:00
Andrew Johnson
28b3b1678c ioc/dbStatic: Add JSON parsing of field values
The parsing removes all white-space outside of quotes from the JSON.
dbRecordField() now strips quotes from simple string values itself.
2016-05-19 01:15:33 -05:00
Andrew Johnson
efb5ba27ae libCom/dbmf: Add dbmfStrcat3() for JSON parsing
Also removed all epicsShareAPI attributes
Made string arguments const char *
2016-05-19 00:58:45 -05:00
Andrew Johnson
574db56740 Make antelope's error messages slightly nicer 2016-05-19 00:51:23 -05:00
Andrew Johnson
998c3c1648 Clean up warnings from gcc 5.2 2016-05-16 14:55:58 -05:00
Andrew Johnson
6a592dc2c0 Support "link(name, lset)" syntax in DBD files
Both Perl and dbStaticLib support included.
Also added a new std/link directory for link types.
Nothing looks up the registered link support tables yet.
2016-05-08 22:57:42 -05:00
Andrew Johnson
ac5c7b0314 Merged Michael's cxxcleanup branch 2016-05-04 17:50:59 -05:00
Michael Davidsaver
d674866219 epicsGuard.h add typedefs linking guard and release 2016-05-02 20:53:51 -04:00
Michael Davidsaver
a1bd644502 drop all templateInstances.cpp
No longer needed by any targets.
2016-05-02 20:51:11 -04:00
Michael Davidsaver
a38dccfb1a add guard/release typedefs for epicsMutex 2016-04-28 09:20:13 -04:00
Michael Davidsaver
17edfd0652 use epicsMin/Max instead of tsMin/Max
Don't remove tsMinMax.h yet as it appeared
in caServerApp template.
2016-04-28 09:20:13 -04:00
Michael Davidsaver
afd48be98c drop unused tsBTree.h 2016-04-28 09:20:13 -04:00
Michael Davidsaver
d92af8c44d remove unused autoPtrDestroy.h 2016-04-28 09:20:13 -04:00
Michael Davidsaver
2af37d076d drop unused epicsOnce 2016-04-28 09:20:13 -04:00
Michael Davidsaver
64c1a28f69 remove unused locationException.h includes 2016-04-28 09:20:13 -04:00
Michael Davidsaver
954874dbd6 drop epicsMemory.h 2016-04-28 09:20:13 -04:00
Michael Davidsaver
673cb24fc2 replace use of epics_auto_ptr w/ eapt_array
add helpers for udpiiu to calculate parameters maxPeriod and nTimers,
allowing them to be const.
Add SearchArray to hold fixed-size array of auto_ptr.
2016-04-28 09:20:13 -04:00
Michael Davidsaver
05c347434b use auto_ptr instead of epics_auto_ptr where applicable 2016-04-28 09:20:13 -04:00
Andrew Johnson
13294f80cc Add basic support and tests for a JSON link address type 2016-04-27 20:47:17 -05:00
Andrew Johnson
778aa18c00 More cleanup 2016-04-27 20:29:16 -05:00
Andrew Johnson
0348c2295b Cleanup 2016-04-26 22:13:12 -05:00
Andrew Johnson
8a5d1a08ad Restore loadLink to lset, move CONSTANT link code into its own source file 2016-04-03 01:29:28 -05:00
Andrew Johnson
1e028d68d8 Move DBLINK support code into its own source file 2016-04-03 00:49:36 -05:00
Andrew Johnson
d33c402b00 Release Notes 2016-03-23 17:15:57 -05:00
Andrew Johnson
bc2a47b849 cvtFastPerform: Rename reserved member names, fix for vxWorks 2016-03-23 16:56:34 -05:00
Andrew Johnson
0a0b9a93a2 Simplify epicsConvertDoubleToFloat() 2016-03-22 18:14:12 -05:00
Andrew Johnson
d949e34c13 More cvtFastPerform changes
Added a converter using std::streambuf (slow!)
Pass buffer size to converters
Added verbose flag and # numbers to measure
Do the small number tests first
2016-03-22 17:47:03 -05:00
Andrew Johnson
db4f208659 Collate and report by precision 2016-03-22 01:01:51 -05:00
Andrew Johnson
e82449171f Restructure cvtFastPerform, fix VxWorks build 2016-03-18 17:45:52 -05:00
Andrew Johnson
e7bba39737 Add int64 record types and device support, from long 2016-03-16 13:14:49 -05:00
Andrew Johnson
f97c1a345e Fix cvtFast and tests
We might still want to change the actual behaviour though,
see the FIXME comments.
2016-03-16 09:44:35 -05:00
Andrew Johnson
4a5a675ef8 Remove development printf() statements 2014-08-24 23:48:32 -05:00
Andrew Johnson
2d4243981f Fix warnings found by clang 2014-07-12 01:12:08 -05:00
Andrew Johnson
2fb0b0763d Implement 64-bit database field types.
Incorporates major reworking of the dbConvert.c file.
if the 64-bit stuff gets rejected most of that should
get pulled in anyway.
2014-07-10 18:13:28 -05:00
518 changed files with 30931 additions and 17761 deletions

12
README
View File

@@ -2,14 +2,14 @@
EPICS Base - the central core of a control system toolkit
---------------------------------------------------------
Copyright (c) 1991-2003 The University of Chicago, as Operator
of Argonne National Laboratory.
Copyright UChicago Argonne LLC, as Operator of Argonne
National Laboratory.
Copyright (c) 1991-2003 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 in the
file LICENSE that is included with this distribution.
EPICS Base is distributed subject to a Software License
Agreement found in the file LICENSE that is included with
this distribution.
---------------------------------------------------------
@@ -20,5 +20,5 @@ Additional information about EPICS including mailing list
archives and subscription instructions, documentation and
training materials, additional components, links to other
websites etc. is available on the EPICS home page at
https://epics.anl.gov/
http://www.aps.anl.gov/epics/

View File

@@ -40,12 +40,11 @@ configuration:
# Environment variables: compiler toolchain
environment:
matrix:
- TOOLCHAIN: 9.0
- TOOLCHAIN: 10.0
- TOOLCHAIN: 11.0
- TOOLCHAIN: 12.0
- TOOLCHAIN: 14.0
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLCHAIN: 2017
- TOOLCHAIN: cygwin
- TOOLCHAIN: mingw
@@ -58,6 +57,8 @@ platform:
matrix:
exclude:
# VS Express installs don't have the 64 bit compiler
- platform: x64
TOOLCHAIN: 9.0
- platform: x64
TOOLCHAIN: 10.0

View File

@@ -1,6 +1,6 @@
:: Universal build script for AppVeyor (https://ci.appveyor.com/)
:: Environment:
:: TOOLCHAIN - toolchain version [10.0/11.0/12.0/14.0/2017/cygwin/mingw]
:: TOOLCHAIN - toolchain version [9.0/10.0/11.0/12.0/14.0/cygwin/mingw]
:: CONFIGURATION - determines EPICS build [dynamic/static]
:: PLATFORM - architecture [x86/x64]
::
@@ -57,22 +57,10 @@ if "%TOOLCHAIN%"=="mingw" (
)
set "VSINSTALL=C:\Program Files (x86)\Microsoft Visual Studio %TOOLCHAIN%"
if not exist "%VSINSTALL%\" set "VSINSTALL=C:\Program Files (x86)\Microsoft Visual Studio\%TOOLCHAIN%\Community"
if not exist "%VSINSTALL%\" goto MSMissing
set "MAKE=C:\tools\make"
echo [INFO] APPVEYOR_BUILD_WORKER_IMAGE=%APPVEYOR_BUILD_WORKER_IMAGE%
if "%OS%"=="64BIT" (
set EPICS_HOST_ARCH=windows-x64%ST%
:: VS 2017
if exist "%VSINSTALL%\VC\Auxiliary\Build\vcvars64.bat" (
call "%VSINSTALL%\VC\Auxiliary\Build\vcvars64.bat"
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
if exist "%VSINSTALL%\VC\vcvarsall.bat" (
call "%VSINSTALL%\VC\vcvarsall.bat" amd64
where cl
@@ -91,19 +79,12 @@ if "%OS%"=="64BIT" (
)
) else (
set EPICS_HOST_ARCH=win32-x86%ST%
:: VS 2017
if exist "%VSINSTALL%\VC\Auxiliary\Build\vcvars32.bat" (
call "%VSINSTALL%\VC\Auxiliary\Build\vcvars32.bat"
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
if exist "%VSINSTALL%\VC\vcvarsall.bat" (
call "%VSINSTALL%\VC\vcvarsall.bat" x86
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
)
if exist "%VSINSTALL%\VC\bin\vcvars32.bat" (
call "%VSINSTALL%\VC\bin\vcvars32.bat"
where cl

View File

@@ -65,6 +65,6 @@ if "%TOOLCHAIN%"=="mingw" (
)
echo [INFO] Installing Make 4.1
curl -fsS --retry 3 -o C:\tools\make-4.1.zip https://epics.anl.gov/download/tools/make-4.1-win64.zip
@powershell -Command "(new-object net.webclient).DownloadFile('https://www.aps.anl.gov/epics/download/tools/make-4.1-win64.zip', 'C:\tools\make-4.1.zip')"
cd \tools
"C:\Program Files\7-Zip\7z" e make-4.1.zip

View File

@@ -17,7 +17,7 @@ ticker() {
CACHEKEY=1
EPICS_HOST_ARCH=`perl src/tools/EpicsHostArch.pl`
EPICS_HOST_ARCH=`sh startup/EpicsHostArch`
[ -e configure/os/CONFIG_SITE.Common.linux-x86 ] || die "Wrong location: $PWD"
@@ -86,5 +86,5 @@ make -j2 $EXTRA
if [ "$TEST" != "NO" ]
then
make tapfiles
make -s test-results
find . -name '*.tap' -print0 | xargs -0 -n1 prove -e cat -f
fi

View File

@@ -20,15 +20,11 @@ else
endif
# Provide a default if the user hasn't set EPICS_HOST_ARCH
#
ifeq ($(origin EPICS_HOST_ARCH), undefined)
# Bootstrapping ...
EHA := $(firstword $(wildcard $(EPICS_BASE)/lib/perl/EpicsHostArch.pl \
$(TOP)/src/tools/EpicsHostArch.pl))
# NB: We use a simply expanded variable here for performance:
export EPICS_HOST_ARCH := $(shell perl $(EHA))
EHA :=
EPICS_HOST_ARCH := $(shell $(CONFIG)/../startup/EpicsHostArch.pl)
endif
#
-include $(CONFIG)/RELEASE
-include $(CONFIG)/RELEASE.$(EPICS_HOST_ARCH)
@@ -77,17 +73,17 @@ ifdef T_A
#
-include $(CONFIG)/os/CONFIG.$(EPICS_HOST_ARCH).$(T_A)
# Site specific target and host-target definitions and overrides
#
-include $(CONFIG)/os/CONFIG_SITE.Common.$(T_A)
-include $(CONFIG)/os/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
# RELEASE file specific definitions
#
ifneq ($(CONFIG),$(TOP)/configure)
-include $(CONFIG)/CONFIG_APP_INCLUDE
endif
# Site specific target and host-target definitions
#
-include $(CONFIG)/os/CONFIG_SITE.Common.$(T_A)
-include $(CONFIG)/os/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
endif # ifdef T_A

View File

@@ -17,14 +17,14 @@ BUILD_CLASS = CROSS
# ifdef CROSS looks better than ifeq ($(BUILD_CLASS),CROSS)
CROSS = YES
GNU_TARGET_INCLUDE_DIR = $(wildcard $(GNU_TARGET:%=$(GNU_DIR)/%/include))
GNU_TARGET_LIB_DIR = $(wildcard $(GNU_TARGET:%=$(GNU_DIR)/%/lib))
GNU_TARGET_INCLUDE_DIR = $(GNU_TARGET:%= $(GNU_DIR)/%/include)
GNU_TARGET_LIB_DIR = $(GNU_TARGET:%= $(GNU_DIR)/%/lib)
CROSS_INCLUDES = $(GNU_TARGET_INCLUDE_DIR:%=-I%)
CROSS_LDFLAGS = $(GNU_TARGET_LIB_DIR:%=-L%)
CROSS_INCLUDES = $(addprefix -I,$(GNU_TARGET_INCLUDE_DIR))
CROSS_LDFLAGS = $(addprefix -L,$(GNU_TARGET_LIB_DIR))
CMPLR_PREFIX_CROSS = $(addsuffix -,$(GNU_TARGET))
CMPLR_PREFIX = $(CMPLR_PREFIX_$(BUILD_CLASS))
CMPLR_PREFIX_CROSS=$(addsuffix -,$(GNU_TARGET))
CMPLR_PREFIX=$(CMPLR_PREFIX_$(BUILD_CLASS))
# Cross builds usually use the gnu compiler
include $(CONFIG)/CONFIG.gnuCommon

View File

@@ -3,13 +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.
#*************************************************************************
#---------------------------------------------------------------
# Epics base directories
# EPICS Base directories
EPICS_BASE_HOST_BIN = $(EPICS_BASE)/bin/$(EPICS_HOST_ARCH)
EPICS_BASE_HOST_LIB = $(EPICS_BASE)/lib/$(EPICS_HOST_ARCH)
@@ -19,12 +18,12 @@ ifdef T_A
endif
#---------------------------------------------------------------
# Epics base Ioc libraries
# EPICS Base Ioc libraries
EPICS_BASE_IOC_LIBS += dbRecStd dbCore ca Com
#---------------------------------------------------------------
# Epics base Host libraries
# EPICS Base Host libraries
EPICS_BASE_HOST_LIBS += cas gdd
EPICS_BASE_HOST_LIBS += ca Com
@@ -37,17 +36,16 @@ ifdef BASE_TOP
SHRLIB_VERSION = $(EPICS_VERSION).$(EPICS_REVISION).$(EPICS_MODIFICATION)
# Windows only allows 2 levels of version numbering
PROD_VERSION = $(EPICS_VERSION).$(EPICS_REVISION)
BASE_CPPFLAGS += -DUSE_TYPED_RSET
endif # BASE_TOP
#---------------------------------------------------------------
# Base c preprocessor flags
BASE_CPPFLAGS =
# osithread default stack
OSITHREAD_USE_DEFAULT_STACK = NO
OSITHREAD_DEFAULT_STACK_FLAGS_YES = -DOSITHREAD_USE_DEFAULT_STACK
OSITHREAD_DEFAULT_STACK_FLAGS_NO =
BASE_CPPFLAGS += $(OSITHREAD_DEFAULT_STACK_FLAGS_$(OSITHREAD_USE_DEFAULT_STACK))
#---------------------------------------------------------------
@@ -59,7 +57,7 @@ TOOLS = $(abspath $(EPICS_BASE_HOST_BIN))
FIND_TOOL = $(firstword $(wildcard $(TOOLS)/$(1) $(TOP)/src/tools/$(1)))
#---------------------------------------------------------------
# Epics base build tools and tool flags
# EPICS Base build tools and tool flags
MAKEBPT = $(TOOLS)/makeBpt$(HOSTEXE)
DBEXPAND = $(PERL) $(TOOLS)/dbdExpand.pl
@@ -69,11 +67,11 @@ REGISTERRECORDDEVICEDRIVER = $(PERL) $(TOOLS)/registerRecordDeviceDriver.pl
CONVERTRELEASE = $(PERL) $(call FIND_TOOL,convertRelease.pl)
FULLPATHNAME = $(PERL) $(TOOLS)/fullPathName.pl
TAPTOJUNIT = $(PERL) $(TOOLS)/tap-to-junit-xml.pl
GENVERSIONHEADER = $(PERL) $(TOOLS)/genVersionHeader.pl $(QUIET_FLAG)
#-------------------------------------------------------
#---------------------------------------------------------------
# tools for installing libraries and products
INSTALL_QUIETLY := $(if $(findstring s,$(MAKEFLAGS)),-q,)
INSTALL = $(PERL) $(TOOLS)/installEpics.pl $(INSTALL_QUIETLY)
INSTALL = $(PERL) $(TOOLS)/installEpics.pl $(QUIET_FLAG)
INSTALL_PRODUCT = $(INSTALL)
INSTALL_LIBRARY = $(INSTALL)
@@ -83,7 +81,7 @@ MKMF = $(PERL) $(TOOLS)/mkmf.pl
REPLACEVAR = $(PERL) $(TOOLS)/replaceVAR.pl
#---------------------------------------------------------------
# private versions of lex/yacc from EPICS
# Our versions of lex (flex) and yacc (antelope)
EYACC = $(TOOLS)/antelope$(HOSTEXE)
ELEX = $(TOOLS)/e_flex$(HOSTEXE) -S$(EPICS_BASE)/include/flex.skel.static
@@ -91,28 +89,6 @@ YACC = $(EYACC)
LEX = $(ELEX)
#---------------------------------------------------------------
# Our use of msi is incompatible with older versions
# The 3.15 version of msi supports new options
MSI3_15 = $(EPICS_BASE_HOST_BIN)/msi
#---------------------------------------------------------------
# External tools and tool flags - must be in path or defined in application
ADL2DL ?= adl2dl
# sch2edif compiler and flags
SCH2EDIF = sch2edif
SCH2EDIF_PATH =
SCH2EDIF_SYSFLAGS = -n -ap -p.+..+$(SCH2EDIF_PATH)+$(CAPFAST_TEMPLATES)/sym+
SCH2EDIF_FLAGS =
# e2db and flags
# - again there is an assumption where edb.def is installed.
E2DB ?= e2db
E2DB_SYSFLAGS = -ate -d $(CAPFAST_TEMPLATES)/edb.def
E2DB_FLAGS =
DBST ?= dbst

View File

@@ -4,7 +4,7 @@
# 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 the file LICENSE that is included with this distribution.
# in the file LICENSE that is included with this distribution.
#*************************************************************************
#
# EPICS Version information
@@ -15,19 +15,30 @@
# EPICS_SITE_VERSION is defined in CONFIG_SITE for sites that want a local
# version number to be included in the reported version string.
# In 3.15 we still define BASE_3_14 so "ifdef BASE_3_14" means
# 3.14 or later, but "ifeq ($(BASE_3_14),YES)" means 3.14 only.
# We define BASE_3_14 and BASE_3_15 as NO and BASE_3_16 as YES, so
# ifdef BASE_3_14
# true for 3.14 or later
# ifdef BASE_3_15
# true for 3.15 or later
# ifeq ($(BASE_3_14),YES)
# true for 3.14.x only
# ifeq ($(BASE_3_15),YES)
# true for 3.15 only
# ifeq ($(BASE_3_16),YES)
# true for 3.16 only.
BASE_3_14 = NO
BASE_3_15 = YES
BASE_3_15 = NO
BASE_3_16 = YES
# EPICS_VERSION must be a number >0 and <256
EPICS_VERSION = 3
# EPICS_REVISION must be a number >=0 and <256
EPICS_REVISION = 15
EPICS_REVISION = 16
# EPICS_MODIFICATION must be a number >=0 and <256
EPICS_MODIFICATION = 6
EPICS_MODIFICATION = 1
# EPICS_PATCH_LEVEL must be a number (win32 resource file requirement)
# Not included if zero

View File

@@ -38,10 +38,6 @@ BUILD_ARCHS = $(EPICS_HOST_ARCH) $(CROSS1) $(CROSS2)
# otherwise override this in os/CONFIG_SITE.<host_arch>.Common
PERL = perl -CSD
#-------------------------------------------------------
# dbst based database optimization default
DB_OPT = NO
#-------------------------------------------------------
# Check configure/RELEASE file for consistency
CHECK_RELEASE_YES = checkRelease
@@ -83,6 +79,7 @@ IOCS_APPL_TOP = $(shell $(FULLPATHNAME) $(INSTALL_LOCATION))
# Make echo output - suppress echoing if make's '-s' flag is set
NOP = :
ECHO = @$(if $(findstring s,$(patsubst T_A=%,,$(MAKEFLAGS))),$(NOP),echo)
QUIET_FLAG := $(if $(findstring s,$(MAKEFLAGS)),-q,)
#-------------------------------------------------------
ifdef T_A
@@ -332,6 +329,14 @@ COMPILE.cpp = $(CCC) $(CPPFLAGS) $(CXXFLAGS) $(INCLUDES)
# C preprocessor command
PREPROCESS.cpp = $(CPP) $(CPPFLAGS) $(INCLUDES) $< > $@
#--------------------------------------------------
# genVersion header defaults
# C macro name
GENVERSIONMACRO = VCSVERSION
# C macro default value (empty to use date+time)
GENVERSIONDEFAULT =
#--------------------------------------------------
# Header dependency file generation

View File

@@ -35,8 +35,10 @@ EPICS_CA_CONN_TMO=30.0
EPICS_CA_REPEATER_PORT=5065
EPICS_CA_SERVER_PORT=5064
EPICS_CA_MAX_ARRAY_BYTES=16384
EPICS_CA_AUTO_ARRAY_BYTES=YES
EPICS_CA_BEACON_PERIOD=15.0
EPICS_CA_MAX_SEARCH_PERIOD=300.0
EPICS_CA_MCAST_TTL=1
EPICS_CAS_BEACON_PERIOD=
EPICS_CAS_BEACON_PORT=
EPICS_CAS_AUTO_BEACON_ADDR_LIST=""

View File

@@ -13,7 +13,7 @@
#
# CONFIG_SITE_ENV - EPICS Environment Parameter Site configuration file
#
# This file is read by the script base/src/libCom/env/bldEnvData.pl
# This file is read by the script base/src/libCom/env/bldEnvdata.pl
# Variable definitions must take the form
# VAR = VALUE
# or
@@ -26,42 +26,31 @@
# Time service:
# EPICS_TIMEZONE
# Local timezone info for vxWorks and RTEMS. The format is
# <name>::<minutesWest>:<startDST>:<endDST>
# where <name> is only used by strftime() for %Z conversions,
# and <startDST> and <endDST> are mmddhh - that is month,day,hour
# e.g. for ANL in 2018: EPICS_TIMEZONE=CUS::360:031102:110402
# The future dates below assume the rules don't get changed;
# see http://www.timeanddate.com/time/dst/2018.html to check.
# local timezone info for vxWorks and RTEMS IOCs. The format is
# <name>::<minutesWest>:<start daylight>:<end daylight>
# where the start and end are mmddhh - that is month,day,hour
# e.g. for ANL in 2016: EPICS_TIMEZONE=CST/CDT::360:031302:110602
#
# DST for 2016 US: Mar 13 - Nov 06
# EU: Mar 27 - Oct 30
# DST for 2017 US: Mar 12 - Nov 05
# EU: Mar 26 - Oct 29
# DST for 2018 US: Mar 11 - Nov 04
# EU: Mar 25 - Oct 28
EPICS_TIMEZONE = CUS::360:031102:110402
#EPICS_TIMEZONE = MET::-60:032502:102803
#
# DST for 2019 US: Mar 10 - Nov 03
# EU: Mar 31 - Oct 27
#EPICS_TIMEZONE = CUS::360:031002:110302
#EPICS_TIMEZONE = MET::-60:033102:102703
#
# DST for 2020 US: Mar 08 - Nov 01
# EU: Mar 29 - Oct 25
#EPICS_TIMEZONE = CUS::360:030802:110102
#EPICS_TIMEZONE = MET::-60:032902:102503
#
# DST for 2021 US: Mar 14 - Nov 07
# EU: Mar 28 - Oct 31
#EPICS_TIMEZONE = CUS::360:031402:110702
#EPICS_TIMEZONE = MET::-60:032802:103103
# (see: http://www.timeanddate.com/time/dst/2016.html etc. )
#
# DST for 2022 US: Mar 13 - Nov 06
# EU: Mar 27 - Oct 30
#EPICS_TIMEZONE = CUS::360:031302:110602
#EPICS_TIMEZONE = MET::-60:032702:103003
# These values are for 2016:
EPICS_TIMEZONE=CST/CDT::360:031302:110602
#EPICS_TIMEZONE=CET/CEST::-60:032702:103002
# EPICS_TS_NTP_INET
# NTP time server ip address for VxWorks and RTEMS.
# IOC will use its boot host if this is not set.
# NTP time server ip address. Uses boot host if not set.
EPICS_TS_NTP_INET=
# IOC Shell:
@@ -69,8 +58,11 @@ EPICS_TS_NTP_INET=
# Prompt string
# IOCSH_HISTSIZE
# Number of lines of command history to keep.
# IOCSH_HISTEDIT_DISABLE
# Prevents use of readline or equivalent if defined.
IOCSH_PS1="epics> "
IOCSH_HISTSIZE=50
IOCSH_HISTEDIT_DISABLE=
# Log Server:
# EPICS_IOC_LOG_INET

View File

@@ -8,10 +8,12 @@
#*************************************************************************
#RULES.Db
# Set db substitutions file suffix
# Set db substitutions and template file suffixes
SUBST_SUFFIX ?= .substitutions
TEMPL_SUFFIX ?= .template
##################################################### vpath
#---------------------------------------------------------------
# vpath
vpath %.pm $(USR_VPATH) $(SRC_DIRS) $(dir $(DBD))
vpath %.pod $(USR_VPATH) $(SRC_DIRS) $(dir $(DBD))
@@ -19,12 +21,13 @@ vpath %.dbd $(USR_VPATH) $(SRC_DIRS) $(dir $(DBD))
vpath %.db $(USR_VPATH) $(SRC_DIRS) $(dir $(DB))
vpath %.vdb $(USR_VPATH) $(SRC_DIRS) $(dir $(DB))
vpath %$(SUBST_SUFFIX) $(USR_VPATH) $(SRC_DIRS) $(COMMON_DIR)
vpath %.template $(USR_VPATH) $(SRC_DIRS) $(COMMON_DIR)
vpath %$(TEMPL_SUFFIX) $(USR_VPATH) $(SRC_DIRS) $(COMMON_DIR)
vpath bpt%.data $(USR_VPATH) $(SRC_DIRS) $(COMMON_DIR)
vpath %.acf $(USR_VPATH) $(SRC_DIRS) $(COMMON_DIR)
vpath %.acs $(USR_VPATH) $(SRC_DIRS) $(COMMON_DIR)
##################################################### dbflags dbdflags
#---------------------------------------------------------------
# dbflags dbdflags
DBD_SEARCH_DIRS = . .. $(COMMON_DIR) $(SRC_DIRS) $(INSTALL_DBD) $(RELEASE_DBD_DIRS)
DB_SEARCH_DIRS = . .. $(COMMON_DIR) $(SRC_DIRS) $(INSTALL_DB) $(RELEASE_DB_DIRS)
@@ -33,13 +36,15 @@ DBDFLAGS = $(USR_DBDFLAGS) $(CMD_DBDFLAGS) $(addprefix -I,$(DBD_SEARCH_DIRS))
DBFLAGS = $($*_DBFLAGS) $(USR_DBFLAGS) $(CMD_DBFLAGS) $(addprefix -I,$(DB_SEARCH_DIRS))
REGRDDFLAGS = $(DBDFLAGS) $($*_REGRDDFLAGS) $(USR_REGRDDFLAGS) $(CMD_REGRDDFLAGS)
##################################################### Targets
#---------------------------------------------------------------
# Targets
# ---------------------------------------------------
# To allow os specific dbd files AND have the -j option work properly,
CROSS_TARGET_OS_TYPES = $(sort $(foreach target, \
$(EPICS_HOST_ARCH) $(CROSS_COMPILER_TARGET_ARCHS),$(firstword $(subst -, ,$(target)))))
CROSS_TARGET_OS_TYPES = $(sort $(foreach target, \
$(EPICS_HOST_ARCH) $(CROSS_COMPILER_TARGET_ARCHS), \
$(firstword $(subst -, ,$(target)))))
DBD += $(foreach type, $(CROSS_TARGET_OS_TYPES), $(DBD_$(type)))
# Users add os specific dbd files to a Makefile as follows
@@ -86,31 +91,28 @@ SOURCE_DB_bbb = $(foreach dir, $(GENERIC_SRC_DIRS), $(SOURCE_DB_aaa) )
SOURCE_DB_aaa = $(addsuffix /$(file), $(dir) )
COMMONS = $(COMMON_DIR)/*.dbd $(COMMON_DIR)/*.db $(COMMON_DIR)/*.h \
$(COMMON_DIR)/*$(SUBST_SUFFIX) $(COMMON_DIR)/*.template
$(COMMON_DIR)/*$(SUBST_SUFFIX) $(COMMON_DIR)/*$(TEMPL_SUFFIX)
# Remove trailing numbers (to 99) on stem
TEMPLATE1=$(patsubst %0,%,$(patsubst %1,%,$(patsubst %2,%,$(patsubst %3,%,$(patsubst %4,%, \
$(patsubst %5,%,$(patsubst %6,%,$(patsubst %7,%,$(patsubst %8,%,$(patsubst %9,%, \
$*))))))))))
TEMPLATE2=$(patsubst %0,%,$(patsubst %1,%,$(patsubst %2,%,$(patsubst %3,%,$(patsubst %4,%, \
$(patsubst %5,%,$(patsubst %6,%,$(patsubst %7,%,$(patsubst %8,%,$(patsubst %9,%, \
$(TEMPLATE1)))))))))))
TEMPLATE3=$(addsuffix .template,$(addprefix ../,$(TEMPLATE2)))
TEMPLATE_FILENAME=$(firstword $(wildcard $($*_TEMPLATE) $(addprefix ../,$($*_TEMPLATE)) ../$*.template $(TEMPLATE3) ../template))
# dbst based database optimization
ifeq '$(DB_OPT)' 'YES'
RAW=.raw
DBS = $(filter %.db,$(DB)) $(addsuffix $(RAW),$(filter %.db,$(DB)))
COMMON_DBS = $(addprefix $(COMMON_DIR)/,$(DBS))
endif
TEMPLATE1 = $(patsubst %0,%,$(patsubst %1,%,$(patsubst %2,%,$(patsubst %3,%, \
$(patsubst %4,%,$(patsubst %5,%,$(patsubst %6,%,$(patsubst %7,%, \
$(patsubst %8,%,$(patsubst %9,%,$*))))))))))
TEMPLATE2 = $(patsubst %0,%,$(patsubst %1,%,$(patsubst %2,%,$(patsubst %3,%, \
$(patsubst %4,%,$(patsubst %5,%,$(patsubst %6,%,$(patsubst %7,%, \
$(patsubst %8,%,$(patsubst %9,%,$(TEMPLATE1)))))))))))
TEMPLATE3 = $(addsuffix $(TEMPL_SUFFIX),$(addprefix ../,$(TEMPLATE2)))
TEMPLATE_FILENAME = $(firstword $(wildcard $($*_TEMPLATE) \
$(addprefix ../,$($*_TEMPLATE)) ../$*$(TEMPL_SUFFIX) $(TEMPLATE3) \
../template))
INSTALL_DB_INSTALLS = $(addprefix $(INSTALL_DB)/,$(notdir $(DB_INSTALLS)))
INSTALL_DBD_INSTALLS = $(addprefix $(INSTALL_DBD)/,$(notdir $(DBD_INSTALLS)))
COMMONDEP_TARGET = $(COMMON_DIR)/$(basename $@)
##################################################### acf files
#---------------------------------------------------------------
# acf files
# An access security configuration file, *.acf, can be created from
# an *.acs file (has format of acf file plus #include "filename" lines)
@@ -123,7 +125,8 @@ ACF_INCLUDES = -I. $(TARGET_INCLUDES) $(USR_INCLUDES)\
ACFDEPENDS_CMD = $(MKMF) -m $@ $(ACF_INCLUDES) $(COMMONDEP_TARGET) $<
ACF_CMD = $(CPP) $(ACF_CPPFLAGS) $(ACF_INCLUDES) $< > $@
##################################################### dependancies
#---------------------------------------------------------------
# dependencies
HINC += $(addsuffix .h,$(DBDINC_NAME))
COMMON_DBDINC += $(addprefix $(COMMON_DIR)/,$(HINC))
@@ -133,12 +136,12 @@ DBDDEPENDS_FILES += $(addsuffix $(DEP),$(HINC) \
$(patsubst $(COMMON_DIR)/%,%, \
$(filter-out $(COMMON_DIR)/bpt%.dbd,$(COMMON_DBDS))))
#####################################################
#---------------------------------------------------------------
ifndef T_A
DEP = .d
TEMPLATE3+=$(addsuffix .template, $(TEMPLATE2))
TEMPLATE3 += $(addsuffix $(TEMPL_SUFFIX), $(TEMPLATE2))
COMMON_DIR = .
INSTALL_DBDS =
@@ -153,18 +156,13 @@ ACTIONS += install
ACTIONS += buildInstall
ACTIONS += runtests tapfiles clean-tests test-results junitfiles
actionArchTargets = $(foreach x, $(ACTIONS),\ $(foreach arch,$(BUILD_ARCHS), $(x)$(DIVIDER)$(arch)))
actionArchTargets = $(foreach action, $(ACTIONS), \
$(foreach arch, $(BUILD_ARCHS), $(action)$(DIVIDER)$(arch)))
cleanArchTargets = $(foreach arch, $(BUILD_ARCHS), clean$(DIVIDER)$(arch))
cleanArchTargets = $(foreach arch,$(BUILD_ARCHS), clean$(DIVIDER)$(arch))
-include $(TOP)/configure/CONFIG_APP_INCLUDE
all: install
ifeq ($(EPICS_HOST_ARCH),$T_A)
host: install
else
# Do nothing
host:
endif
install: buildInstall
@@ -172,20 +170,30 @@ buildInstall : build
rebuild: clean install
.PHONY: all host $(ACTIONS)
.PHONY: all $(ACTIONS)
$(actionArchTargets) $(BUILD_ARCHS): install
$(cleanArchTargets): clean
.PHONY: $(BUILD_ARCHS) $(actionArchTargets) $(cleanArchTargets)
endif # T_A defined
else
# T_A is defined
ifeq ($(EPICS_HOST_ARCH),$(T_A))
host: install
else
host:
endif
.PHONY: host
endif # T_A
ifneq (,$(strip $(DBDDEPENDS_FILES)))
-include $(DBDDEPENDS_FILES)
endif
##################################################### build dependancies, clean rule
#---------------------------------------------------------------
# build dependancies, clean rule
inc : $(COMMON_INC) $(INSTALL_INC)
@@ -205,7 +213,8 @@ db_clean :
realclean: clean
##################################################### Dependency files
#---------------------------------------------------------------
# Dependency files
%Record.h$(DEP): $(COMMON_DIR)/%Record.dbd
@$(RM) $@
@@ -256,19 +265,19 @@ menu%.h$(DEP): ../menu%.dbd
@$(DBEXPAND) -D $(DBDFLAGS) -o $(COMMONDEP_TARGET) $($*_DBD) > $@
@echo "$(COMMONDEP_TARGET): ../Makefile" >> $@
%.db$(RAW)$(DEP): %$(SUBST_SUFFIX)
%.db$(DEP): %$(SUBST_SUFFIX)
@$(RM) $@
$(MSI3_15) -D $(DBFLAGS) -o $(COMMONDEP_TARGET) -S$< $(TEMPLATE_FILENAME) > $@
%.db$(RAW)$(DEP): ../%$(SUBST_SUFFIX)
%.db$(DEP): ../%$(SUBST_SUFFIX)
@$(RM) $@
$(MSI3_15) -D $(DBFLAGS) -o $(COMMONDEP_TARGET) -S$< $(TEMPLATE_FILENAME) > $@
%.db$(RAW)$(DEP): %.template
%.db$(DEP): %$(TEMPL_SUFFIX)
@$(RM) $@
$(MSI3_15) -D $(DBFLAGS) -o $(COMMONDEP_TARGET) $< > $@
%.db$(RAW)$(DEP): ../%.template
%.db$(DEP): ../%$(TEMPL_SUFFIX)
@$(RM) $@
$(MSI3_15) -D $(DBFLAGS) -o $(COMMONDEP_TARGET) $< > $@
@@ -282,14 +291,8 @@ menu%.h$(DEP): ../menu%.dbd
.PRECIOUS: %$(DEP)
##################################################### CapFast filter
$(COMMON_DIR)/%.edf: ../%.sch $(DEPSCHS)
@$(RM) $@
@if [ ! -f cad.rc -a -r ../cad.rc ] ; then ln -s ../cad.rc ; fi
$(SCH2EDIF) $(SCH2EDIF_SYSFLAGS) $(SCH2EDIF_FLAGS) -o $@ $<
##################################################### Substitution files
#---------------------------------------------------------------
# Substitution files
# WARNING: CREATESUBSTITUTIONS script needs output dir on command line
@@ -310,25 +313,21 @@ $(INSTALL_DB)/%$(SUBST_SUFFIX): ../%$(SUBST_SUFFIX)
.PRECIOUS: $(COMMON_DIR)/%$(SUBST_SUFFIX)
##################################################### Template files
#---------------------------------------------------------------
# Template files
$(COMMON_DIR)/%.template: $(COMMON_DIR)/%.edf
@$(RM) $@
$(E2DB) $(E2DB_SYSFLAGS) $(E2DB_FLAGS) -n $@.VAR $<
@$(REPLACEVAR) < $@.VAR > $@
@$(RM) $@.VAR
$(INSTALL_DB)/%.template: %.template
$(INSTALL_DB)/%$(TEMPL_SUFFIX): %$(TEMPL_SUFFIX)
$(ECHO) "Installing template file $@"
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
$(INSTALL_DB)/%.template: ../%.template
$(INSTALL_DB)/%$(TEMPL_SUFFIX): ../%$(TEMPL_SUFFIX)
$(ECHO) "Installing template file $@"
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
.PRECIOUS: $(COMMON_DIR)/%.template
.PRECIOUS: $(COMMON_DIR)/%$(TEMPL_SUFFIX)
##################################################### INC files
#---------------------------------------------------------------
# INC files
$(COMMON_DIR)/%Record.h: $(COMMON_DIR)/%Record.dbd
@$(RM) $(notdir $@)
@@ -362,7 +361,8 @@ $(COMMON_DIR)/menu%.h: ../menu%.dbd
.PRECIOUS: $(COMMON_DIR)/%.h
##################################################### DBD files
#---------------------------------------------------------------
# DBD files
$(COMMON_DIR)/bpt%.dbd: bpt%.data
@$(RM) $(notdir $@)
@@ -425,7 +425,8 @@ $(foreach file, $(DBD_INSTALLS), $(eval $(call DBD_INSTALLS_template, $(file))))
.PRECIOUS: $(COMMON_DBDS) $(COMMON_DIR)/%.dbd
##################################################### HTML files
#---------------------------------------------------------------
# HTML files
$(COMMON_DIR)/%.html: %.dbd.pod $(TOOLS)/dbdToHtml.pl
@$(RM) $(notdir $@)
@@ -444,37 +445,44 @@ $(COMMON_DIR)/%.html: %.pm $(TOOLS)/podToHtml.pl
$(COMMON_DIR)/%.html: ../%.pm $(TOOLS)/podToHtml.pl
@$(RM) $(notdir $@)
$(PERL) $(TOOLS)/podToHtml.pl -o $(notdir $@) $<
$(PERL) $(TOOLS)/podToHtml.pl -s -o $(notdir $@) $<
@$(MKDIR) $(dir $@)
@$(MV) $(notdir $@) $@
$(COMMON_DIR)/%.html: ../%.pl $(TOOLS)/podToHtml.pl
@$(RM) $(notdir $@)
$(PERL) $(TOOLS)/podToHtml.pl -s -o $(notdir $@) $<
@$(MV) $(notdir $@) $@
.PRECIOUS: $(COMMON_DIR)/%.html %.html
##################################################### DB files
#---------------------------------------------------------------
# DB files
$(COMMON_DIR)/%.db$(RAW): $(COMMON_DIR)/%.edf
$(COMMON_DIR)/%.db: $(COMMON_DIR)/%.edf
$(E2DB) $(E2DB_SYSFLAGS) $(E2DB_FLAGS) -n $*.VAR $<
@$(REPLACEVAR) < $*.VAR > $@
@$(RM) $*.VAR
$(COMMON_DIR)/%.db$(RAW): %$(SUBST_SUFFIX)
$(COMMON_DIR)/%.db: %$(SUBST_SUFFIX)
$(ECHO) "Inflating database from $< $(TEMPLATE_FILENAME)"
@$(RM) $(notdir $@)
$(MSI3_15) $(DBFLAGS) -o $(notdir $@) -S$< $(TEMPLATE_FILENAME)
@$(MV) $(notdir $@) $@
$(COMMON_DIR)/%.db$(RAW): ../%$(SUBST_SUFFIX)
$(COMMON_DIR)/%.db: ../%$(SUBST_SUFFIX)
$(ECHO) "Inflating database from $< $(TEMPLATE_FILENAME)"
@$(RM) $(notdir $@)
$(MSI3_15) $(DBFLAGS) -o $(notdir $@) -S$< $(TEMPLATE_FILENAME)
@$(MV) $(notdir $@) $@
$(COMMON_DIR)/%.db$(RAW): %.template
$(COMMON_DIR)/%.db: %$(TEMPL_SUFFIX)
$(ECHO) "Inflating database from $<"
@$(RM) $(notdir $@)
$(MSI3_15) $(DBFLAGS) -o $(notdir $@) $<
@$(MV) $(notdir $@) $@
$(COMMON_DIR)/%.db$(RAW): ../%.template
$(COMMON_DIR)/%.db: ../%$(TEMPL_SUFFIX)
$(ECHO) "Inflating database from $<"
@$(RM) $(notdir $@)
$(MSI3_15) $(DBFLAGS) -o $(notdir $@) $<
@@ -492,22 +500,6 @@ $(COMMON_DIR)/%.acf: ../%.acs
.PRECIOUS: $(COMMON_DIR)/%.acf
# dbst based database optimization
ifeq '$(DB_OPT)' 'YES'
$(COMMON_DIR)/%.db$(RAW): ../%.db
@$(RM) $@
$(CP) $< $@
$(COMMON_DIR)/%.db: $(COMMON_DIR)/%.db$(RAW)
$(ECHO) "Optimizing database $@"
@$(RM) $@
$(DBST) . $< -d > $@
.PRECIOUS: $(COMMON_DIR)/%.db
.PRECIOUS: $(DB:%=$(COMMON_DIR)/%$(RAW))
else
$(INSTALL_DB)/%: %
$(ECHO) "Installing $@"
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
@@ -515,7 +507,6 @@ $(INSTALL_DB)/%: %
$(INSTALL_DB)/%: ../%
$(ECHO) "Installing $@"
@$(INSTALL) -d -m $(INSTALL_PERMISSIONS) $< $(@D)
endif
$(INSTALL_DB)/%.db: $(COMMON_DIR)/%.db
$(ECHO) "Installing created db file $@"
@@ -531,8 +522,8 @@ $(foreach file, $(DB_INSTALLS), $(eval $(call DB_INSTALLS_template, $(file))))
.PRECIOUS: $(COMMON_DIR)/%.edf
.PRECIOUS: $(COMMON_DBS)
##################################################### register record,device,driver support
#---------------------------------------------------------------
# register record,device,driver support
%_registerRecordDeviceDriver.cpp: $(COMMON_DIR)/%.dbd
@$(RM) $@
@@ -548,4 +539,3 @@ $(foreach file, $(DB_INSTALLS), $(eval $(call DB_INSTALLS_template, $(file))))
.PRECIOUS: %_registerRecordDeviceDriver.cpp
##################################################### END OF FILE

View File

@@ -25,6 +25,7 @@ vpath %.html $(USR_VPATH) $(ALL_SRC_DIRS)
vpath %.skel.static $(USR_VPATH) $(ALL_SRC_DIRS)
vpath %.y $(USR_VPATH) $(ALL_SRC_DIRS)
vpath %.l $(USR_VPATH) $(ALL_SRC_DIRS)
vpath %.pl $(USR_VPATH) $(ALL_SRC_DIRS)
#---------------------------------------------------------------
@@ -102,7 +103,6 @@ endif
# Products and Object libraries
#
PRODTARGETS += $(PRODNAME) $(MUNCHNAME) $(CTDT_SRCS) $(CTDT_OBJS) $(NMS)
TESTPRODTARGETS += $(TESTPRODNAME) $(TESTMUNCHNAME)
#---------------------------------------------------------------
# Test specifications and test result files
@@ -141,7 +141,7 @@ rebuild: clean install
build: inc
build: $(OBJSNAME) $(LIBTARGETS) $(PRODTARGETS) $(TESTPRODTARGETS) \
build: $(OBJSNAME) $(LIBTARGETS) $(PRODTARGETS) $(TESTPRODNAME) \
$(TARGETS) $(TESTSCRIPTS) $(INSTALL_LIB_INSTALLS)
inc : $(COMMON_INC) $(INSTALL_INC) $(INSTALL_CONFIGS)
@@ -159,21 +159,20 @@ clean: build_clean
build_clean:
$(ECHO) "Cleaning"
@$(RM) *.i *$(OBJ) *.a \
@$(RM) *.i *$(OBJ) *.a $(TESTPRODNAME) \
$(LIBNAME) $(TESTLIBNAME) $(SHRLIBNAME) $(TESTSHRLIBNAME) \
$(DLLSTUB_LIBNAME) $(TESTDLLSTUB_LIBNAME) \
$(LOADABLE_SHRLIBNAME) \
$(INC) $(TARGETS) $(TDS) $(CLEANS) \
*.out MakefileInclude *.manifest *.exp \
$(COMMON_INC) $(HDEPENDS_FILES) $(PRODTARGETS) $(TESTPRODTARGETS) \
$(COMMON_INC) $(HDEPENDS_FILES) $(PRODTARGETS) \
$(TESTSCRIPTS) $(TAPFILES) $(JUNITFILES)
ifdef RES
@$(RM) *$(RES)
endif
# Sort mkdir targets to remove duplicates & make parents first
$(DIRECTORY_TARGETS):
$(MKDIR) $(sort $@)
$(DIRECTORY_TARGETS) :
$(MKDIR) $@
# Install LIB_INSTALLS libraries before linking executables
$(TESTPRODNAME) $(PRODNAME): | $(INSTALL_LIB_INSTALLS)
@@ -256,13 +255,15 @@ YACCOPT ?= $($*_YACCOPT)
$(MV) $*.tab.c $*.c
$(if $(findstring -d, $(YACCOPT)),$(MV) $*.tab.h $*.h,)
# must be a separate rule since when not using '-d' the
# must be a seperate rule since when not using '-d' the
# prefix for .h will be different then .c
%.h : %.c %.y
%.c: %.l
@$(RM) $*.yy.c
$(LEX) $(LEXOPT) -t $< > $*.yy.c
@$(RM) $@
$(LEX) $(LEXOPT) -o$@ $<
$(MV) $*.yy.c $@
#---------------------------------------------------------------
# Libraries, shared/DLL and stubs
@@ -321,10 +322,6 @@ $(MUNCHNAME): %$(MUNCH_SUFFIX): $(MUNCH_DEPENDS) %$(EXE)
@$(RM) $@
$(MUNCH_CMD)
$(TESTMUNCHNAME): %$(MUNCH_SUFFIX): $(MUNCH_DEPENDS) %$(EXE)
@$(RM) $@
$(MUNCH_CMD)
#---------------------------------------------------------------
# GeSys modules for RTEMS
$(MODNAME): %$(MODEXT): %$(EXE)
@@ -351,7 +348,7 @@ testspec: $(TESTSCRIPTS)
test-results: tapfiles
ifneq ($(TAPFILES),)
ifdef RUNTESTS_ENABLED
prove --failures --ext .tap --exec "$(CAT)" --color $(TAPFILES)
prove --failures --ext .tap --exec cat --color $(TAPFILES)
endif
endif
@@ -386,6 +383,14 @@ endif
@$(RM) $@
$(PERL) $(TOOLS)/makeTestfile.pl $@ $<
#---------------------------------------------------------------
# Generate header with version number from VCS
ifneq ($(GENVERSION),)
$(COMMON_DIR)/$(GENVERSION): FORCE
$(GENVERSIONHEADER) -t $(TOP) -N $(GENVERSIONMACRO) -V "$(GENVERSIONDEFAULT)" $@
endif
#---------------------------------------------------------------
# Install rules for BIN_INSTALLS and LIB_INSTALLS
@@ -520,7 +525,7 @@ $(INSTALL_TEMPLATES_SUBDIR)/%: %
.PHONY: all host inc build install clean rebuild buildInstall build_clean
.PHONY: runtests tapfiles clean-tests test-results junitfiles
.PHONY: checkRelease warnRelease noCheckRelease
.PHONY: checkRelease warnRelease noCheckRelease FORCE
endif # BASE_RULES_BUILD
# EOF RULES_BUILD

View File

@@ -38,17 +38,6 @@ $(foreach target, $(PROD) $(TESTPROD), \
#-----------------------------------------------------------------------
# These must be done before PROD2_template
define TESTLIBRARY_template
$(1)_DIR = .
TESTBUILD_LIBRARY += $$(if $$(strip $$($(1)_OBJSNAME) $$(LIBRARY_OBJS)),$(1),)
endef
$(foreach target, $(TESTLIBRARY), \
$(eval $(call TESTLIBRARY_template,$(strip $(target)))))
#-----------------------------------------------------------------------
define TARGET2_template
$(1)_LDLIBS += $$($(1)_LIBS)
$(1)_LDLIBS += $$(if $$(strip $$($(1)_LIBS_$(OS_CLASS))), \
@@ -134,6 +123,16 @@ $(foreach target, $(LIBRARY), \
#-----------------------------------------------------------------------
define LIBRARY3_template
$(1)_DIR = .
TESTBUILD_LIBRARY += $$(if $$(strip $$($(1)_OBJSNAME) $$(LIBRARY_OBJS)),$(1),)
endef
$(foreach target, $(TESTLIBRARY), \
$(eval $(call LIBRARY3_template,$(strip $(target)))))
#-----------------------------------------------------------------------
define LOADABLE_LIBRARY_template
LOADABLE_BUILD_LIBRARY += $$(if $$(strip $$($(1)_OBJSNAME) $$(LIBRARY_OBJS)),$(1),)

View File

@@ -136,13 +136,6 @@ MOD_LDFLAGS = $(OPT_LDFLAGS) $(TARGET_LDFLAGS) $(USR_LDFLAGS) $(POSIX_LDFLAGS) \
LINK.mod = $(CCC) -o $@ $(PRODDIR_LDFLAGS) $(MOD_LDFLAGS)
LINK.mod += $(PROD_LDFLAGS) $(PROD_LD_OBJS) $(PROD_LD_RESS) $(MOD_LDLIBS)
#--------------------------------------------------
# Here munching means creating a bootable object binary
ifdef MUNCH_SUFFIX
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
TESTMUNCHNAME = $(TESTPRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
endif
#--------------------------------------------------
# RTEMS has neither shared libraries nor dynamic loading
STATIC_BUILD=YES

View File

@@ -15,6 +15,7 @@ ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_CLUSTER_SPACE=5120
OP_SYS_LDLIBS += -lbspExt
MUNCH_SUFFIX = .boot
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
define MUNCH_CMD
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary $< $@
endef

View File

@@ -13,6 +13,7 @@ ARCH_DEP_CFLAGS += -DHAVE_PPCBUG
OP_SYS_LDLIBS += -lbspExt
MUNCH_SUFFIX = .boot
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
define MUNCH_CMD
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< rtems
gzip -f9 rtems

View File

@@ -7,6 +7,7 @@ ARCH_DEP_CFLAGS += -DHAVE_PPCBUG
ARCH_DEP_CFLAGS += -DNVRAM_INDIRECT
MUNCH_SUFFIX = .boot
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
define MUNCH_CMD
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< rtems
gzip -f9 rtems

View File

@@ -15,6 +15,7 @@ ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_CLUSTER_SPACE=5120
OP_SYS_LDLIBS += -lbspExt
MUNCH_SUFFIX = .boot
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
define MUNCH_CMD
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary $< $@
endef

View File

@@ -16,6 +16,7 @@ ARCH_DEP_CFLAGS += -DBSP_NVRAM_BASE_ADDR=0xf1110000
OP_SYS_LDLIBS += -lbspExt
MUNCH_SUFFIX = .boot
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
define MUNCH_CMD
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary $< $@
endef

View File

@@ -8,6 +8,7 @@
RTEMS_TARGET_CPU=i386
MUNCH_SUFFIX = .boot
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
define MUNCH_CMD
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< temp.bin
$(BIN2BOOT) $@ 0x00097E00 \

View File

@@ -9,6 +9,7 @@ RTEMS_TARGET_CPU = m68k
ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL
MUNCH_SUFFIX = .boot
MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
define MUNCH_CMD
$(RTEMS_TOOLS)/bin/$(OBJCOPY_FOR_TARGET) -O binary -R .comment -S $< $@
endef

View File

@@ -15,14 +15,5 @@ ARCH_CLASS = xscale
ifeq ($(BUILD_CLASS),CROSS)
VALID_BUILDS = Ioc
GNU_TARGET = xscale_be
CMPLR_PREFIX = $(GNU_TARGET:%=%-)
# Configure for readline if requested
OP_SYS_INCLUDES += $(READLINE_DIR:%=-I%/include)
READLINE_LDFLAGS = $(READLINE_DIR:%=-L%/lib)
RUNTIME_LDFLAGS_READLINE_YES_NO = $(READLINE_DIR:%=-Wl,-rpath,%/lib)
RUNTIME_LDFLAGS += \
$(RUNTIME_LDFLAGS_READLINE_$(LINKER_USE_RPATH)_$(STATIC_BUILD))
SHRLIBDIR_LDFLAGS += $(READLINE_LDFLAGS)
PRODDIR_LDFLAGS += $(READLINE_LDFLAGS)
CMPLR_PREFIX = $(addsuffix -,$(GNU_TARGET))
endif

View File

@@ -23,15 +23,13 @@ STATIC_LDFLAGS_YES= -Wl,-Bstatic
STATIC_LDFLAGS_NO=
STATIC_LDLIBS_YES= -Wl,-Bdynamic
# Set runtime path for shared libraries if USE_RPATH=YES and STATIC_BUILD=NO
SHRLIBDIR_RPATH_LDFLAGS_YES_NO = $(SHRLIB_DEPLIB_DIRS:%=-Wl,-rpath,%)
SHRLIBDIR_LDFLAGS += \
$(SHRLIBDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH)_$(STATIC_BUILD))
# Set runtime path for shared libraries
SHRLIBDIR_RPATH_LDFLAGS_YES += $(SHRLIB_DEPLIB_DIRS:%=-Wl,-rpath,%)
SHRLIBDIR_LDFLAGS += $(SHRLIBDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH))
# Set runtime path for products if USE_RPATH=YES and STATIC_BUILD=NO
PRODDIR_RPATH_LDFLAGS_YES_NO = $(PROD_DEPLIB_DIRS:%=-Wl,-rpath,%)
PRODDIR_LDFLAGS += \
$(PRODDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH)_$(STATIC_BUILD))
# Set runtime path for products
PRODDIR_RPATH_LDFLAGS_YES += $(PROD_DEPLIB_DIRS:%=-Wl,-rpath,%)
PRODDIR_LDFLAGS += $(PRODDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH))
# Link libraries controlled by COMMANDLINE_LIBRARY
# The newest Linux versions only need readline, older ones need both

View File

@@ -1,7 +1,7 @@
# CONFIG.Common.vxWorksCommon
#
# Definitions for vxWorks target archs
# Sites may override these definitions in CONFIG_SITE.Common.vxWorksCommon
# Override these definitions in CONFIG_SITE.Common.vxWorksCommon
# or CONFIG_SITE.<host>.vxWorksCommon
#-------------------------------------------------------
@@ -63,8 +63,6 @@ VXWORKS_MAJOR_VERSION = $(basename $(basename $(VXWORKS_VERSION)))
# These are needed for vxWorks 6.x; the GNU toolset version number
# is in the path to the compiler tools:
VX_GNU_VERSION_5.4 = 2.95
VX_GNU_VERSION_5.5 = 2.96
VX_GNU_VERSION_6.0 = 3.3.2
VX_GNU_VERSION_6.1 = 3.3.2
VX_GNU_VERSION_6.2 = 3.3.2
@@ -80,49 +78,47 @@ VX_GNU_VERSION = $(VX_GNU_VERSION_$(VXWORKS_VERSION))
VX_GNU_MAJOR_VERSION = $(basename $(basename $(VX_GNU_VERSION)))
#--------------------------------------------------
# Fix WIND_BASE for vxWorks 6.x on linux
# NB: We know the value of WIND_HOST_TYPE here, but not VXWORKS_VERSION
# Fix old Linux WIND_HOST_TYPE
ifeq ($(WIND_HOST_TYPE),x86-linux)
WIND_HOST_TYPE_5 = x86-linux
WIND_HOST_TYPE_6 = x86-linux2
WIND_HOST_TYPE = $(WIND_HOST_TYPE_$(VXWORKS_MAJOR_VERSION))
WIND_HOST_TYPE = x86-linux2
endif
#--------------------------------------------------
# vxWorks directory definitions
VX_DIR_5 = $(WIND_BASE)
VX_DIR_6 = $(WIND_BASE)/vxworks-$(VXWORKS_VERSION)
VX_DIR = $(VX_DIR_$(VXWORKS_MAJOR_VERSION))
VX_DIR = $(WIND_BASE)/vxworks-$(VXWORKS_VERSION)
VX_INCLUDE_DIRS_5 = $(VX_DIR)/target/h
VX_INCLUDE_DIRS_6 = $(VX_DIR)/target/h $(VX_DIR)/target/h/wrn/coreip
GNU_TARGET_INCLUDE_DIR = $(VX_INCLUDE_DIRS_$(VXWORKS_MAJOR_VERSION))
GNU_TARGET_INCLUDE_DIR = $(VX_DIR)/target/h $(VX_DIR)/target/h/wrn/coreip
#--------------------------------------------------
# vxWorks GNU directories
GNU_DIR_5 = $(WIND_BASE)/host/$(WIND_HOST_TYPE)
GNU_DIR_6 = $(WIND_BASE)/gnu/$(VX_GNU_VERSION)-vxworks-$(VXWORKS_VERSION)/$(WIND_HOST_TYPE)
GNU_DIR = $(GNU_DIR_$(VXWORKS_MAJOR_VERSION))
GNU_DIR = $(WIND_BASE)/gnu/$(VX_GNU_VERSION)-vxworks-$(VXWORKS_VERSION)/$(WIND_HOST_TYPE)
#--------------------------------------------------
# This finds nm on any supported VxWorks version
# Wind River moved nm out of GNU_BIN in some versions
NMPROG = $(CMPLR_PREFIX)nm$(CMPLR_SUFFIX)$(HOSTEXE)
NM = $(firstword $(wildcard $(WIND_BASE)/*/$(WIND_HOST_TYPE)/bin/$(NMPROG)))
WORKBENCH_BIN = $(WIND_BASE)/workbench-$(WORKBENCH_VERSION)/$(WIND_HOST_TYPE)/bin
UTILITIES_BIN = $(WIND_BASE)/utilities-$(UTILITIES_VERSION)/$(WIND_HOST_TYPE)/bin
NM_DIR_6.4 = $(WORKBENCH_BIN)
NM_DIR_6.5 = $(WORKBENCH_BIN)
NM_DIR_6.6 = $(WORKBENCH_BIN)
NM_DIR_6.7 = $(GNU_BIN)
NM_DIR_6.8 = $(UTILITIES_BIN)
NM_DIR_6.9 = $(UTILITIES_BIN)
NM_DIR = $(firstword $(NM_DIR_$(VXWORKS_VERSION)) $(GNU_BIN))
NM = $(NM_DIR)/$(CMPLR_PREFIX)nm$(CMPLR_SUFFIX)$(HOSTEXE)
#--------------------------------------------------
# A linker script is essential for munching from vxWorks 6.6 onwards
# (i.e. with versions that use gcc 4.1.2 or later). It can be used
# with any vxWorks 5 or 6 version, but apparently should not be used
# when compiling for 68K (which isn't supported in vxWorks 6 anyway)
# (i.e. with versions that use gcc 4.1.2 or later).
MUNCH_LDFLAGS_6 = -T $(VX_DIR)/target/h/tool/gnu/ldscripts/link.OUT
MUNCH_LDFLAGS = $(MUNCH_LDFLAGS_$(VXWORKS_MAJOR_VERSION))
#--------------------------------------------------
# These are required by some of the Wind River tools
export WIND_BASE
export WIND_HOME = $(WIND_BASE)
export WIND_HOST_TYPE
export TOOL_FAMILY = GNU
@@ -131,11 +127,10 @@ export TOOL_FAMILY = GNU
OP_SYS_CPPFLAGS += -DvxWorks=vxWorks
OP_SYS_CFLAGS += -fno-builtin
# Fix for vxWorks 5 headers that use macros defined in vxWorks.h but
# Fix for vxWorks headers that use macros defined in vxWorks.h but
# which don't actually include vxWorks.h themselves, for example the
# target/h/sys/stat.h file which uses ULONG. This also stops dbDefs.h
# from defining the OFFSET macro, which generates lots of warnings in
# both vxWorks 5 and 6.
# from defining the OFFSET macro, which generates lots of warnings.
OP_SYS_INCLUDE_CPPFLAGS += -include $(VX_DIR)/target/h/vxWorks.h
#--------------------------------------------------
@@ -148,7 +143,6 @@ OPT_CXXFLAGS_YES = -O2
CODE_CFLAGS =
#
# For vxWorks versions before 6.3 we need this g++ compiler flag
CODE_CXXFLAGS_5 = -fno-implicit-templates
CODE_CXXFLAGS_6.0 = -fno-implicit-templates
CODE_CXXFLAGS_6.1 = -fno-implicit-templates
CODE_CXXFLAGS_6.2 = -fno-implicit-templates
@@ -170,8 +164,6 @@ OSITHREAD_USE_DEFAULT_STACK = NO
#--------------------------------------------------
# Link definitions
CROSS_LDFLAGS =
#
LINK.cpp = $(LD) -o $@ $(STATIC_LDFLAGS) $(PRODDIR_LDFLAGS) $(LDFLAGS)
LINK.cpp += $(PROD_LDFLAGS) $(PROD_LD_OBJS) $(PROD_LD_RESS) $(PROD_LDLIBS)

View File

@@ -8,7 +8,7 @@
CP = cp
MV = mv
RM = rm -f
MKDIR = mkdir
MKDIR = mkdir -p
RMDIR = rm -rf
CAT = cat

View File

@@ -65,14 +65,14 @@ GNU = NO
#
# Darwin shared libraries
#
SHRLIB_LDFLAGS = -dynamiclib -undefined dynamic_lookup \
SHRLIB_LDFLAGS = -dynamiclib -flat_namespace -undefined suppress \
-install_name $(shell $(FULLPATHNAME) $(INSTALL_LIB))/$@ \
$(addprefix -compatibility_version , $(SHRLIB_VERSION)) \
$(addprefix -current_version , $(SHRLIB_VERSION))
SHRLIB_SUFFIX_BASE = .dylib
SHRLIB_SUFFIX = $(addprefix ., $(SHRLIB_VERSION))$(SHRLIB_SUFFIX_BASE)
LOADABLE_SHRLIB_LDFLAGS = -bundle -undefined dynamic_lookup
LOADABLE_SHRLIB_LDFLAGS = -bundle -flat_namespace -undefined suppress
#
# Position-independent code is the default on Darwin.

View File

@@ -7,4 +7,4 @@
#Include definitions common to unix hosts
include $(CONFIG)/os/CONFIG.UnixCommon.Common
WIND_HOST_TYPE = x86-linux
WIND_HOST_TYPE = x86-linux2

View File

@@ -7,4 +7,4 @@
#Include definitions common to unix hosts
include $(CONFIG)/os/CONFIG.UnixCommon.Common
WIND_HOST_TYPE = x86-linux
WIND_HOST_TYPE = x86-linux2

View File

@@ -7,4 +7,4 @@
#Include definitions common to unix hosts
include $(CONFIG)/os/CONFIG.UnixCommon.Common
WIND_HOST_TYPE = x86-linux
WIND_HOST_TYPE = x86-linux2

View File

@@ -7,4 +7,4 @@
#Include definitions common to unix hosts
include $(CONFIG)/os/CONFIG.UnixCommon.Common
WIND_HOST_TYPE = x86-linux
WIND_HOST_TYPE = x86-linux2

View File

@@ -7,4 +7,4 @@
#Include definitions common to unix hosts
include $(CONFIG)/os/CONFIG.UnixCommon.Common
WIND_HOST_TYPE = x86-linux
WIND_HOST_TYPE = x86-linux2

View File

@@ -11,14 +11,19 @@ GNU_TARGET = arm-linux
CMPLR_SUFFIX =
CMPLR_PREFIX = $(addsuffix -,$(GNU_TARGET))
# Provide a link-time path for readline if needed
OP_SYS_INCLUDES += $(READLINE_DIR:%=-I%/include)
READLINE_LDFLAGS = $(READLINE_DIR:%=-L%/lib)
RUNTIME_LDFLAGS_READLINE_YES_NO = $(READLINE_DIR:%=-Wl,-rpath,%/lib)
RUNTIME_LDFLAGS += \
$(RUNTIME_LDFLAGS_READLINE_$(LINKER_USE_RPATH)_$(STATIC_BUILD))
SHRLIBDIR_LDFLAGS += $(READLINE_LDFLAGS)
PRODDIR_LDFLAGS += $(READLINE_LDFLAGS)
# Provide a link-time path for shared libraries
SHRLIBDIR_RPATH_LDFLAGS_YES += $(SHRLIB_DEPLIB_DIRS:%=-Wl,-rpath-link,%)
SHRLIBDIR_LDFLAGS += $(SHRLIBDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH))
# Provide a link-time path for products
PRODDIR_RPATH_LDFLAGS_YES += $(PROD_DEPLIB_DIRS:%=-Wl,-rpath-link,%)
PRODDIR_LDFLAGS += $(PRODDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH))
# Provide a link-time path for readline
RUNTIME_LDFLAGS_READLINE_YES = -Wl,-rpath-link,$(GNU_DIR)/lib
RUNTIME_LDFLAGS_READLINE = $(RUNTIME_LDFLAGS_READLINE_$(LINKER_USE_RPATH))
RUNTIME_LDFLAGS_READLINE_CURSES = $(RUNTIME_LDFLAGS_READLINE_$(LINKER_USE_RPATH))
RUNTIME_LDFLAGS_READLINE_NCURSES = $(RUNTIME_LDFLAGS_READLINE_$(LINKER_USE_RPATH))
# Library flags
STATIC_LDFLAGS_YES= -Wl,-Bstatic

View File

@@ -7,4 +7,4 @@
#Include definitions common to unix hosts
include $(CONFIG)/os/CONFIG.UnixCommon.Common
WIND_HOST_TYPE = x86-linux
WIND_HOST_TYPE = x86-linux2

View File

@@ -79,20 +79,16 @@ CPP = cl -nologo -C -E
# Configure OS vendor C++ compiler
#
# __STDC__=0 gives us both:
# 1) define STDC for code (pretend ANSI conformance)
# 2) set it to 0 to use MS C "extensions" (open for _open etc.)
# because MS uses: if __STDC__ ... disable many nice things
#
# -EHsc - generate code for exceptions
# -GR - generate code for run time type identification
#
CCC = cl -EHsc -GR
# Other compiler flags, used for CPP, C and C++
#
# -FC - Show absolute path of source file in diagnostics
# -D__STDC__=0 gives us both:
# 1) define STDC for code (pretend ANSI conformance)
# 2) set it to 0 to use MS C "extensions" (open for _open etc.)
# because MS uses: if __STDC__ ... disable many nice things
#
CODE_CPPFLAGS += -nologo -FC -D__STDC__=0
CODE_CPPFLAGS += -nologo -D__STDC__=0
CODE_CPPFLAGS += -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE
@@ -140,16 +136,6 @@ STATIC_LDLIBS_NO=
STATIC_LDFLAGS=
RANLIB=
#
# option needed for parallel builds with Visual Studio 2015 onward
#
# -FS Force Synchronous PDB Writes
ifneq ($(VisualStudioVersion),)
OPT_CXXFLAGS_NO += -FS
OPT_CFLAGS_NO += -FS
endif
#
# add -profile here to run the ms profiler
# -LTCG whole program optimization

View File

@@ -1,4 +1,10 @@
# CONFIG_SITE.Common.linux-xscale_be
#
# Site specific definitions for all linux-xscale_be target builds.
# Site specific definitions for linux-xscale_be target builds.
#-------------------------------------------------------
# Set GNU_DIR to point to directory containing the tool-chain
# APS:
GNU_DIR = /usr/local/vw/xscale_be

View File

@@ -1,21 +1,13 @@
# CONFIG_SITE.Common.vxWorksCommon
#
# Site specific definitions for vxWorks target builds.
# Only the local epics system manager should modify this file
# Compiler options can vary with the vxWorks version number, so we
# need to know that. However don't include any third-level digits
# (e.g. the .2 in 5.5.2) because we don't need them.
# need to know that. Do not include any third-level digits.
# Note: vxWorks 5.4.x (Tornado 2.0.x) is not supported
# Note: vxWorks 5.4.x and 5.5.x (Tornado 2.x) are not supported.
# VxWorks 6.0 through 6.5 use older, untested versions of GCC.
#VXWORKS_VERSION = 5.5
#VXWORKS_VERSION = 6.0
#VXWORKS_VERSION = 6.1
#VXWORKS_VERSION = 6.2
#VXWORKS_VERSION = 6.3
#VXWORKS_VERSION = 6.4
#VXWORKS_VERSION = 6.5
#VXWORKS_VERSION = 6.6
#VXWORKS_VERSION = 6.7
#VXWORKS_VERSION = 6.8
@@ -27,8 +19,19 @@ VXWORKS_VERSION = 6.9
# CONFIG_SITE.$(EPICS_HOST_ARCH).vxWorksCommon file.
# WIND_BASE is where you installed the Wind River software.
# Under vxWorks 6.x this is *not* the same as the old VX_DIR setting
#WIND_BASE = /usr/local/vw/tornado22-$(ARCH_CLASS)
WIND_BASE = /usr/local/vw/vxWorks-$(VXWORKS_VERSION)
#WIND_BASE = /ade/vxWorks/$(VXWORKS_VERSION)
# WorkBench Version number, if you're using vxWorks 6.x
#WORKBENCH_VERSION = 2.6
#WORKBENCH_VERSION = 3.0
#WORKBENCH_VERSION = 3.2
WORKBENCH_VERSION = 3.3
# Utilities Version number, required from vxWorks 6.8 and later
UTILITIES_VERSION = 1.0

View File

@@ -7,25 +7,8 @@
GNU_TARGET = arm-xilinx-linux-gnueabi
# Set GNU tools install path
# Examples are installations at the APS:
# This is the install path at APS:
GNU_DIR = /usr/local/vw/zynq-2011.09
#GNU_DIR = /usr/local/Xilinx/SDK/2016.3/gnu/arm/lin
#GNU_DIR = /APSshare/XilinxSDK/2015.4/gnu/arm/lin
# If cross-building shared libraries and the paths on the target machine are
# different than on the build host, you should uncomment the lines below to
# disable putting runtime library paths in products and shared libraries.
# You will also need to provide another way for programs to find their shared
# libraries at runtime, such as by setting LD_LIBRARY_PATH or by using
# mechanisms related to /etc/ld.so.conf
#SHRLIBDIR_RPATH_LDFLAGS_YES_NO =
#PRODDIR_RPATH_LDFLAGS_YES_NO =
# Note: It may be simpler to just set STATIC_BUILD=YES here and not
# try to use shared libraries at all in these circumstances.
# To use libreadline, point this to its install prefix
#READLINE_DIR = $(GNU_DIR)
#READLINE_DIR = /tools/cross/linux-x86.linux-arm/readline
# See CONFIG_SITE.Common.linux-arm for other COMMANDLINE_LIBRARY values
#COMMANDLINE_LIBRARY = READLINE
# With a Xilinx SDK, it'll be something like
#GNU_DIR = /usr/local/zynq/Xilinx/SDK/2015.4/gnu/arm/lin

View File

@@ -1,11 +0,0 @@
# CONFIG_SITE.linux-x86.linux-xscale_be
#
# Site specific definitions for linux-x86 host - linux-xscale_be targets
#-------------------------------------------------------
# Set GNU_DIR to point to directory containing the tool-chain
GNU_DIR = /usr/local/vw/xscale_be
# If readline is available, configure it
READLINE_DIR = $(GNU_DIR)/target/usr
COMMANDLINE_LIBRARY = READLINE

View File

@@ -14,10 +14,10 @@
#GNU_DIR = /usr/local
# Different distribution cross-build packages use different prefixes:
# Ubuntu:
#CMPLR_PREFIX = i686-w64-mingw32-
# RHEL:
CMPLR_PREFIX = i686-pc-mingw32-
# Ubuntu, RHEL7:
CMPLR_PREFIX = i686-w64-mingw32-
# RHEL6:
#CMPLR_PREFIX = i686-pc-mingw32-
# Debian?
#CMPLR_PREFIX = i586-mingw32msvc-

View File

@@ -1,7 +0,0 @@
# CONFIG_SITE.linux-x86_64.linux-xscale_be
#
# Site specific settings for linux-x86_64 host - linux-xscale_be target
#-------------------------------------------------------
# Inherit setting from linux-x86
include $(CONFIG)/os/CONFIG_SITE.linux-x86.linux-xscale_be

View File

@@ -4,25 +4,37 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Known Problems in R3.15.6</title>
<title>Known Problems in Base-3.16.1</title>
</head>
<body>
<h1 style="text-align: center">EPICS Base R3.15.6: Known Problems</h1>
<h1 style="text-align: center">EPICS Base R3.16.1: Known Problems</h1>
<p>Any patch files linked below should be applied at the root of the
base-3.15.6 tree. Download them, then use the GNU Patch program as
base-3.16.1 tree. Download them, then use the GNU Patch program as
follows:</p>
<blockquote><pre>% <b>cd <i>/path/to/</i>base-3.15.6</b>
<blockquote><pre>% <b>cd <i>/path/to/</i>base-3.16.1</b>
% <b>patch -p1 &lt; <i>/path/to/</i>file.patch</b></pre></blockquote>
<p>The following significant problems have been reported with this
version of EPICS Base:</p>
<p>The following problems were known by the developers at the time of this
release:</p>
<ul>
<li>None known as yet.</li>
<!-- Items added after release should be formatted thusly:
<li>YYYY-MM-DD: Description of problem.
<a href="fix.patch">This patch</a> fixes the problem.
...</li>
-->
<li>IOCs running on some versions of Cygwin may display warnings at iocInit
about duplicate EPICS CA Address list entries. These warnings might be due
to a bug in Cygwin; they are benign and can be ignored.</li>
<li>64-bit Windows builds of the CAS library may not work with some compilers.
The code in <tt>src/legacy/gdd</tt> is incompatible with the LLP64 model
that Windows uses for its 64-bit ABI.</li>
</ul>

View File

@@ -1,24 +1,24 @@
Installation Instructions
EPICS Base Release 3.15.6
EPICS Base Release 3.16.1
--------------------------------------------------------------------------
Table of Contents
* What is EPICS base?
* What is new in this release?
* Copyright
* Supported platforms
* Supported compilers
* Software requirements
* Host system storage requirements
* Documentation
* Directory Structure
* Build related components
* Building EPICS base (Unix and Win32)
* Example application and extension
* Multiple host platforms
* What is EPICS base?
* What is new in this release?
* Copyright
* Supported platforms
* Supported compilers
* Software requirements
* Host system storage requirements
* Documentation
* Directory Structure
* Build related components
* Building EPICS base (Unix and Win32)
* Example application and extension
* Multiple host platforms
--------------------------------------------------------------------------
@@ -85,17 +85,17 @@
as processes on the host platform.
vxWorks
You must have vxWorks 5.5.x or 6.x installed if any of your target
systems are vxWorks systems; the C++ compiler for vxWorks 5.4 is now too
old to support. The vxWorks installation provides the cross-compiler and
header files needed to build for these targets. The absolute path to and
the version number of the vxWorks installation must be set in the
You must have vxWorks 6 installed if any of your target systems are
vxWorks systems; the C++ compilers for vxWorks 5.x are now too old to
support. The vxWorks installation provides the cross-compiler and header
files needed to build for these targets. The absolute path to and the
version number of the vxWorks installation must be set in the
base/configure/os/CONFIG_SITE.Common.vxWorksCommon file or in one of its
target-specific overrides.
Consult the vxWorks 5.x or vxWorks 6.x EPICS web pages about and the
vxWorks documentation for information about configuring your vxWorks
operating system for use with EPICS.
Consult the vxWorks 6.x EPICS web pages and the vxWorks documentation
for information about configuring your vxWorks operating system for use
with EPICS.
RTEMS
For RTEMS targets, you need RTEMS core and toolset version 4.9.2 or
@@ -166,11 +166,12 @@
base/startup directory - contains scripts to set environment and path
EpicsHostArch Shell script to set EPICS_HOST_ARCH env variable
unix.csh C shell script to set path and env variables
unix.sh Bourne shell script to set path and env variables
win32.bat Bat file example to configure win32-x86 target
windows.bat Bat file example to configure windows-x64 target
EpicsHostArch C shell script to set EPICS_HOST_ARCH env variable
EpicsHostArch.pl Perl script to set EPICS_HOST_ARCH env variable
Site.profile bourne shell script to set path and env variables
Site.cshrc c shell script to set path and env variables
cygwin.bat WIN32 bat file to set cygwin path and env variables
win32.bat WIN32 bat file to set path and env variables
base/configure directory - contains build definitions and rules

View File

@@ -21,7 +21,7 @@ of my Bash login script (~/.bash_login):
#
EPICS_BASE="${HOME}/src/EPICS/base"
EPICS_EXTENSIONS="${HOME}/src/EPICS/extensions"
<strong>.</strong> "${EPICS_BASE}"/startup/unix.sh
<strong>.</strong> "${EPICS_BASE}"/startup/Site.profile
</pre>
</li>
<li>

View File

@@ -9,7 +9,7 @@
<BODY>
<CENTER>
<H1>Installation Instructions</H1>
<H2>EPICS Base Release 3.15.6</H2><BR>
<H2>EPICS Base Release 3.16.1</H2><BR>
</CENTER>
<HR>
<H3> Table of Contents</H3>
@@ -90,17 +90,16 @@
as processes on the host platform.</P>
<P><B>vxWorks</B><BR>
You must have vxWorks 5.5.x or 6.x installed if any of your target systems are
vxWorks systems; the C++ compiler for vxWorks 5.4 is now too old to support.
The vxWorks installation provides the cross-compiler and header files needed to
You must have vxWorks 6 installed if any of your target systems are vxWorks
systems; the C++ compilers for vxWorks 5.x are now too old to support. The
vxWorks installation provides the cross-compiler and header files needed to
build for these targets. The absolute path to and the version number of the
vxWorks installation must be set in the
base/configure/os/CONFIG_SITE.Common.vxWorksCommon file or in one of its
target-specific overrides.</P>
<P>Consult the <a href="https://epics.anl.gov/base/tornado.php">vxWorks
5.x</a> or <a href="https://epics.anl.gov/base/vxWorks6.php">vxWorks
6.x</a> EPICS web pages about and the vxWorks documentation for information
<P>Consult the <a href="http://www.aps.anl.gov/epics/base/vxWorks6.php">vxWorks
6.x</a> EPICS web pages and the vxWorks documentation for information
about configuring your vxWorks operating system for use with EPICS.</P>
<P><B>RTEMS</B><BR>
@@ -129,7 +128,7 @@
<H3><A NAME="0_0_8"> Documentation</A></H3>
<BLOCKQUOTE>EPICS documentation is available through the
<a href="https://epics.anl.gov/">EPICS website</a> at Argonne.
<a href="http://www.aps.anl.gov/epics/">EPICS website</a> at Argonne.
<P>Release specific documentation can also be found in the base/documentation
directory of the distribution.</BLOCKQUOTE>
@@ -177,11 +176,12 @@
<H4>base/startup directory - contains scripts to set environment and path</H4>
<PRE>
EpicsHostArch Shell script to set EPICS_HOST_ARCH env variable
unix.csh C shell script to set path and env variables
unix.sh Bourne shell script to set path and env variables
win32.bat Bat file example to configure win32-x86 target
windows.bat Bat file example to configure windows-x64 target
EpicsHostArch C shell script to set EPICS_HOST_ARCH env variable
EpicsHostArch.pl Perl script to set EPICS_HOST_ARCH env variable
Site.profile bourne shell script to set path and env variables
Site.cshrc c shell script to set path and env variables
cygwin.bat WIN32 bat file to set cygwin path and env variables
win32.bat WIN32 bat file to set path and env variables
</PRE>
<H4>base/configure directory - contains build definitions and rules</H4>
@@ -190,12 +190,12 @@
CONFIG.CrossCommon Cross build definitions
CONFIG.gnuCommon Gnu compiler build definitions for all archs
CONFIG_ADDONS Definitions for &lt;osclass&gt; and DEFAULT options
CONFIG_APP_INCLUDE
CONFIG_APP_INCLUDE
CONFIG_BASE EPICS base tool and location definitions
CONFIG_BASE_VERSION Definitions for EPICS base version number
CONFIG_COMMON Definitions common to all builds
CONFIG_ENV Definitions of EPICS environment variables
CONFIG_FILE_TYPE
CONFIG_FILE_TYPE
CONFIG_SITE Site specific make definitions
CONFIG_SITE_ENV Site defaults for EPICS environment variables
MAKEFILE Installs CONFIG* RULES* creates
@@ -206,9 +206,9 @@
RULES_ARCHS Definitions and rules for building architectures
RULES_BUILD Build and install rules and definitions
RULES_DIRS Definitions and rules for building subdirectories
RULES_EXPAND
RULES_FILE_TYPE
RULES_TARGET
RULES_EXPAND
RULES_FILE_TYPE
RULES_TARGET
RULES_TOP Rules specific to a &lt;top&gt; dir (uninstall and tar)
Sample.Makefile Sample makefile with comments
</PRE>
@@ -340,7 +340,7 @@ Files in the base/startup directory have been provided to
<H3><A NAME="0_0_13"> Example application and extension</A></H3>
<BLOCKQUOTE>A perl tool, makeBaseApp.pl is included in the distribution
file. This script will create a sample application that can be built
and then executed to try out this release of base.
and then executed to try out this release of base.
<P>
Instructions for building and executing the 3.15 example application
@@ -350,8 +350,8 @@ Files in the base/startup directory have been provided to
create and build an example application in a user created &lt;top&gt;
directory. It also explains how to run the example application on a
vxWorks ioc or as a process on the host system.
By running the example application as a host-based IOC, you will be
able to quickly implement a complete EPICS system and be able to run channel
By running the example application as a host-based IOC, you will be
able to quickly implement a complete EPICS system and be able to run channel
access clients on the host system.
<P>

File diff suppressed because it is too large Load Diff

View File

@@ -33,29 +33,27 @@
<h1>EPICS Base Release Procedures &amp; Checklist</h1>
<p>This document describes the procedures and provides a checklist of tasks
that should be performed when creating new releases of EPICS Base.</p>
that should be performed when creating production releases of EPICS Base.</p>
<h3>The Release Process</h3>
<p>The version released on the Feature Freeze date is designated the first
pre-release, <tt>-pre1</tt>. The first Release Candidate <tt>-rc1</tt> is the
pre-release, <tt>-pre1</tt>. The first release candidate <tt>-rc1</tt> is the
first version that has undergone widespread testing and which has no known
problems in it that are slated to be fixed in this release. New versions should
be made at 2-weekly intervals during the testing and debugging period, and will
be designated as either pre-release versions or Release Candidates by the
Release Manager. After a Release Candidate has been available to the whole
be made at about weekly intervals during the testing and debugging period, and
will be designated as either pre-release or release candidate versions by the
Release Manager. After a release candidate has been available to the whole
community for testing for at least a week without any additional problems being
reported or significant changes being committed, the branch can be designated as
the final release version.</p>
<h3>Roles</h3>
<p>The following roles are required. The individuals named here have have been
responsible for these tasks in the past and are expected to continue in the
relevent roles unless the Release Manager designates otherwise:</p>
<p>The following roles are used below:</p>
<dl>
<dt><strong>Release Manager</strong> (Ralph Lange)</dt>
<dt><strong>Release Manager</strong> ()</dt>
<dd>Responsible for managing and tagging the release</dd>
<dt><strong>Platform Developers</strong> (optional)</dt>
<dd>Responsible for individual operating system platforms</dd>
@@ -133,36 +131,40 @@ relevent roles unless the Release Manager designates otherwise:</p>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Tag the module in Git, using these tag conventions:
<td>Tag the module in Git using these tag conventions:
<ul>
<li>
<tt>R3.15.6-pre1</tt>
<tt>R3.16.1-pre<i>n</i></tt>
&mdash; pre-release tag
</li>
<li>
<tt>R3.15.6-rc1</tt>
<tt>R3.16.1-rc<i>n</i></tt>
&mdash; release candidate tag
</li>
</ul>
<blockquote><tt>
cd base-3.15<br />
git tag -m 'RL: Tagged for 3.15.6-rc1' R3.15.6-rc1
cd base-3.16<br />
git tag -m 'ANJ: Tagged for 3.16.1-rc1' R3.16.1-rc1
</tt></blockquote>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Export the tagged version into a tarfile. The <tt>make-tar.sh</tt>
script generates a gzipped tarfile directly from the tag, excluding the
files and directories that are only used for continuous integration:
<td>Export the tagged version into a tarfile. This command generates a
gzipped tarfile directly from the repository, excluding those files and
directories needed only for continuous integration:
<blockquote><tt>
cd base-3.15<br />
git archive --prefix=base-3.15.6-rc1/ --output=base-3.15.6-rc1.tar.gz R3.15.6-rc1 configure documentation LICENSE Makefile README src startup
cd base-3.16<br />
git archive
--prefix=base-3.16.1-rc1/
--output=../base-3.16.1-rc1.tar.gz
R3.16.1-rc1
configure documentation LICENSE Makefile README src startup
</tt></blockquote>
Create a GPG signature file of the tarfile as follows:
<blockquote><tt>
gpg --armor --sign --detach-sig base-3.15.6-rc1.tar.gz
gpg --armor --sign --detach-sig base-3.16.1-rc1.tar.gz
</tt></blockquote>
</td>
</tr>
@@ -256,7 +258,7 @@ relevent roles unless the Release Manager designates otherwise:</p>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Obtain a positive <q>Ok to release</q> from all platform developers
once a Release Candidate version has gone a whole week without any
once a release candidate version has gone a whole week without any
issues being reported.</td>
</tr>
<tr>
@@ -273,23 +275,28 @@ relevent roles unless the Release Manager designates otherwise:</p>
<td>Release Manager</td>
<td>Tag the module in Git:
<blockquote><tt>
cd base-3.15<br />
git tag -m 'RL: Tagged for 3.15.6' R3.15.6
cd base-3.16<br />
git tag -m 'ANJ: Tagged for 3.16.1' R3.16.1</i>
</tt></blockquote>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Export the tagged version into a tarfile. Note that this command
generates a gzipped tarfile directly from the repository:
<td>Export the tagged version into a tarfile. This command generates a
gzipped tarfile directly from the repository, excluding those files and
directories needed only for continuous integration:
<blockquote><tt>
cd base-3.15<br />
git archive --prefix=base-3.15.6/ --output=base-3.15.6.tar.gz R3.15.6 configure documentation LICENSE Makefile README src startup
cd base-3.16<br />
git archive
--prefix=base-3.16.1/
--output=../base-3.16.1.tar.gz
R3.16.1
configure documentation LICENSE Makefile README src startup
</tt></blockquote>
Create a GPG signature file of the tarfile as follows:
<blockquote><tt>
gpg --armor --sign --detach-sig base-3.15.6.tar.gz
gpg --armor --sign --detach-sig base-3.16.1.tar.gz
</tt></blockquote>
</td>
</tr>

View File

@@ -314,11 +314,21 @@ is used.</p>
<td>i &gt;= 16384</td>
<td>16384</td>
</tr>
<tr>
<td>EPICS_CA_AUTO_ARRAY_BYTES</td>
<td>{YES, NO}</td>
<td>YES</td>
</tr>
<tr>
<td>EPICS_CA_MAX_SEARCH_PERIOD</td>
<td>r &gt; 60 seconds</td>
<td>300</td>
</tr>
<tr>
<td>EPICS_CA_MCAST_TTL</td>
<td>r &gt; 1</td>
<td>1</td>
</tr>
<tr>
<td>EPICS_TS_MIN_WEST</td>
<td>-720 &lt; i &lt;720 minutes</td>
@@ -746,6 +756,12 @@ in the variable EPICS_TS_MIN_WEST.</p>
<h3><a name="Configurin1">Configuring the Maximum Array Size</a></h3>
<p>From version R3.16.1, the default setting of EPICS_CA_AUTO_ARRAY_BYTES=YES
will cause the software to ignore EPICS_CA_MAX_ARRAY_BYTES and attempt to
allocate network buffer space as needed by the particular client connection
using malloc. Setting EPICS_CA_AUTO_ARRAY_BYTES=NO will configure the software
to respect the EPICS_CA_MAX_ARRAY_BYTES setting as described below instead.</p>
<p>Starting with version R3.14 the environment variable
EPICS_CA_MAX_ARRAY_BYTES determines the size of the largest array that may pass
through CA. Prior to this version only arrays smaller than 16k bytes could be
@@ -768,11 +784,7 @@ array larger than EPICS_CA_MAX_ARRAY_BYTES it will return ECA_TOLARGE.</p>
by multiplying the number of elements by the size of a single element, but
neglect to add additional bytes for the compound data types (for example
DBR_GR_DOUBLE) commonly used by the more sophisticated client side
applications. <em>Based on this confusion, one could arrive at the conclusion
that EPICS_CA_MAX_ARRAY_BYTES might have been better named
EPICS_CA_MAX_DATUM_BYTES, or that the software should be changed internally to
round the users request up by the size of the maximum scalar datum (nothing has
been done to address this issue so far).</em></p>
applications.</p>
<h3><a name="Configurin2">Configuring a CA Server</a></h3>
@@ -1009,7 +1021,7 @@ d:/user/epics/base-3.15/lib/win32-x86/Com.lib</code></p>
<h2><a name="CommandUtils">Command Line Utilities</a></h2>
<h3><a name="acctst">acctst</a></h3>
<pre>acctst &lt;PV name&gt; [progress logging level] [channel duplication count]
<pre>acctst &lt;PV name&gt; [progress logging level] [channel duplication count]
[test repetition count] [enable preemptive callback]</pre>
<h4>Description</h4>
@@ -2079,7 +2091,7 @@ example, be beneficial when tuning an archiver installation.</p>
<p>Significant performance gains can be realized when the CA client library
doesn't wait for a response to return from the server after each request. All
requests which require interaction with a CA server are accumulated (buffered)
and not forwarded to the IOC until one of <code>ca_flush_io()</code>,
and not forwarded to the IOC until one of <code>ca_flush_io()</code>,
<code>ca_pend_io()</code>, <code>ca_pend_event()</code>, or
<code>ca_sg_block()</code> are called allowing several operations to be
efficiently sent over the network together. Any process variable values written
@@ -2103,16 +2115,16 @@ shouldn't test the success of a CA function call by checking to see if the
returned value is zero as is the UNIX convention. Below are several methods to
test CA function returns. See <a href="#ca_signal"><code>ca_signal()</code> and
<code>SEVCHK()</code></a> for more information on this topic.</p>
<pre>status = ca_XXXX();
SEVCHK( status, "ca_XXXX() returned failure status");
<pre>status = ca_XXXX();
SEVCHK( status, "ca_XXXX() returned failure status");
if ( status &amp; CA_M_SUCCESS ) {
printf ( "The requested ca_XXXX() operation didn't complete successfully");
}
if ( status &amp; CA_M_SUCCESS ) {
printf ( "The requested ca_XXXX() operation didn't complete successfully");
}
if ( status != ECA_NORMAL ) {
if ( status != ECA_NORMAL ) {
printf("The requested ca_XXXX() operation didn't complete successfully because \"%s\"\n",
ca_message ( status ) );
ca_message ( status ) );
}</pre>
<h3><a name="Channel">Channel Access Data Types</a></h3>
@@ -2285,7 +2297,7 @@ int main ( int argc, char ** argv )
unsigned nBytes;
unsigned elementCount;
char timeString[32];
unsigned i;
unsigned i;
chid chan;
double sum;
int status;
@@ -2328,7 +2340,7 @@ int main ( int argc, char ** argv )
epicsTimeToStrftime ( timeString, sizeof ( timeString ),
"%a %b %d %Y %H:%M:%S.%f", &amp; pTD-&gt;stamp );
printf ( "The sum of elements in %s at %s was %f\n",
printf ( "The sum of elements in %s at %s was %f\n",
argv[1], timeString, sum );
ca_clear_channel ( chan );
@@ -2359,7 +2371,7 @@ executing within the user's callback function.</p>
<pre>typedef struct event_handler_args {
void *usr; /* user argument supplied with request */
chanId chid; /* channel id */
long type; /* the type of the item returned */
long type; /* the type of the item returned */
long count; /* the element count of the item returned */
const void *dbr; /* a pointer to the item returned */
int status; /* ECA_XXX status of the requested op from the server */
@@ -2382,7 +2394,7 @@ attached to the request, an exception handler is executed in the client. The
default exception handler prints a message on the console and exits if the
exception condition is severe. Certain internal exceptions within the CA client
library, and failures detected by the SEVCHK macro may also cause the exception
handler to be invoked. To modify this behavior see
handler to be invoked. To modify this behavior see
<code><a href="#ca_add_exception_event">ca_add_exception_event</a>()</code>.</p>
<h3><a name="Server">Server and Client Share the Same Address Space on The Same
@@ -2674,14 +2686,6 @@ automatically released by the system when the process exits and
vxWorks or RTEMS no cleanup occurs unless the application calls
<code>ca_context_destroy()</code>.</p>
<p>Note: This operation blocks until any user callbacks for any channel
created in the current context have run to completion. If callbacks take a
lock (mutex) then it is the user's responsibility to ensure that this lock
is not held when <code>ca_clear_context()</code> is called, otherwise a
deadlock may ensue. (See also
<code><a href="#ca_clear_channel">ca_clear_channel</a>()</code> and
<code><a href="#ca_clear_event">ca_clear_subscription</a>()</code>.)</p>
<h4>Returns</h4>
<p>ECA_NORMAL - Normal successful completion</p>
@@ -2754,7 +2758,7 @@ time.</p>
</dl>
<dl>
<dt><code>USERFUNC</code></dt>
<dd>Optional pointer to the user's callback function to be run when the
<dd>Optional address of the user's callback function to be run when the
connection state changes. Casual users of channel access may decide to
set this field to null or 0 if they do not need to have a callback
function run in response to each connection state change event.
@@ -2827,12 +2831,6 @@ efficiently sent over the network in one message.</p>
clearing a channel does shutdown and reclaim any channel state change event
subscriptions (monitors) registered with the channel.</p>
<p>Note: This operation blocks until any user callbacks for this channel
have run to completion. If callbacks take a lock (mutex) then it is the
user's responsibility to ensure that this lock is not held when
<code>ca_clear_channel()</code> is called, otherwise a deadlock may ensue.
(See also <code><a href="#ca_clear_event">ca_clear_subscription</a>()</code>.)</p>
<h4>Arguments</h4>
<dl>
<dt><code>CHID</code></dt>
@@ -2847,16 +2845,16 @@ user's responsibility to ensure that this lock is not held when
<h3><code><a name="ca_put">ca_put()</a></code></h3>
<pre>#include &lt;cadef.h&gt;
int ca_put ( chtype TYPE,
chid CHID, void *PVALUE );
int ca_array_put ( chtype TYPE, unsigned long COUNT,
int ca_put ( chtype TYPE,
chid CHID, void *PVALUE );
int ca_array_put ( chtype TYPE, unsigned long COUNT,
chid CHID, const void *PVALUE);
typedef void ( caEventCallBackFunc ) (struct event_handler_args);
int ca_put_callback ( chtype TYPE,
chid CHID, const void *PVALUE,
caEventCallBackFunc PFUNC, void *USERARG );
int ca_array_put_callback ( chtype TYPE, unsigned long COUNT,
chid CHID, const void *PVALUE,
int ca_put_callback ( chtype TYPE,
chid CHID, const void *PVALUE,
caEventCallBackFunc PFUNC, void *USERARG );
int ca_array_put_callback ( chtype TYPE, unsigned long COUNT,
chid CHID, const void *PVALUE,
caEventCallBackFunc PFUNC, void *USERARG );</pre>
<h4>Description</h4>
@@ -2935,7 +2933,7 @@ but they do not cause the record to be processed.</p>
</dl>
<dl>
<dt><code>PFUNC</code></dt>
<dd>Pointer to a <a href="#User">user supplied callback function</a> to be
<dd>address of <a href="#User">user supplied callback function</a> to be
run when the requested operation completes</dd>
</dl>
<dl>
@@ -3043,7 +3041,7 @@ when a CA get request is initiated.</p>
</dl>
<dl>
<dt><code>USERFUNC</code></dt>
<dd>Pointer to a <a href="#User">user supplied callback function</a> to be
<dd>Address of <a href="#User">user supplied callback function</a> to be
run when the requested operation completes.</dd>
</dl>
<dl>
@@ -3083,7 +3081,7 @@ when a CA get request is initiated.</p>
typedef void ( caEventCallBackFunc ) (struct event_handler_args);
int ca_create_subscription ( chtype TYPE, unsigned long COUNT,
chid CHID, unsigned long MASK,
caEventCallBackFunc USERFUNC, void *USERARG,
caEventCallBackFunc USERFUNC, void *USERARG,
evid *PEVID );</pre>
<h4>Description</h4>
@@ -3144,8 +3142,8 @@ indicating the current state of the channel.</p>
<dd>channel identifier</dd>
</dl>
<dl>
<dt><code>USERFUNC</code></dt>
<dd>Pointer to a <a href="#User">user supplied callback function</a> to
<dt><code>USRERFUNC</code></dt>
<dd>The address of <a href="#User">user supplied callback function</a> to
be invoked with each subscription update.</dd>
</dl>
<dl>
@@ -3167,7 +3165,7 @@ indicating the current state of the channel.</p>
<dt><code>MASK</code></dt>
<dd>A mask with bits set for each of the event trigger types requested. The
event trigger mask must be a <em>bitwise or</em> of one or more of the
following constants.
following constants.
<ul>
<li>DBE_VALUE - Trigger events when the channel value exceeds the
monitor dead band</li>
@@ -3214,13 +3212,6 @@ and not forwarded to the server until one of <code>ca_flush_io()</code>, <code>c
<code>ca_pend_event()</code>, or <code>ca_sg_block()</code> are called. This allows several requests to be
efficiently sent together in one message.</p>
<p>Note: This operation blocks until any user callbacks for this channel
have run to completion. If callbacks take a lock (mutex) then it is the
user's responsibility to ensure that this lock is not held when
<code>ca_clear_subscription()</code> is called, otherwise a deadlock may
ensue. (See also <code><a
href="#ca_clear_channel">ca_clear_channel</a>()</code>.)</p>
<h4>Arguments</h4>
<dl>
<dt>EVID</dt>
@@ -3385,7 +3376,7 @@ becomes full.</p>
<h3><code><a name="ca_signal">ca_signal()</a></code></h3>
<pre>#include &lt;cadef.h&gt;
int ca_signal ( long CA_STATUS, const char * CONTEXT_STRING );
int ca_signal ( long CA_STATUS, const char * CONTEXT_STRING );
void SEVCHK( CA_STATUS, CONTEXT_STRING );</pre>
<h4>Description</h4>
@@ -3402,7 +3393,7 @@ recommended error handler for simple applications which do not wish to write
code testing the status returned from each channel access call.</p>
<h4>Examples</h4>
<pre>status = ca_context_create (...);
<pre>status = ca_context_create (...);
SEVCHK ( status, "Unable to create a CA client context" );</pre>
<p>If the application only wishes to print the message associated with an error
@@ -3426,7 +3417,7 @@ this purpose.</p>
<h3><code><a
name="ca_add_exception_event">ca_add_exception_event()</a></code></h3>
<pre>#include &lt;cadef.h&gt;
<pre>#include &lt;cadef.h&gt;
typedef void (*pCallback) ( struct exception_handler_args HANDLERARGS );
int ca_add_exception_event ( pCallback USERFUNC, void *USERARG );</pre>
@@ -3450,7 +3441,7 @@ field should not be used.</p>
<h4>Arguments</h4>
<dl>
<dt><code>USERFUNC</code></dt>
<dd>Pointer to a user callback function to be executed when exceptions
<dd>Address of user callback function to be executed when an exceptions
occur. Passing a null value causes the default exception handler to be
reinstalled. The following structure is passed by value to the user's
callback function. Currently, the <code>op</code> field can be one of
@@ -3585,7 +3576,7 @@ default handler uses fprintf to send messages to 'stderr'.</p>
<h4>Arguments</h4>
<dl>
<dt><code>PFUNC</code></dt>
<dd>A pointer to a user supplied callback handler to be invoked when CA
<dd>The address of a user supplied callback handler to be invoked when CA
prints diagnostic messages. Installing a null pointer will cause the
default callback handler to be reinstalled.</dd>
</dl>
@@ -3633,9 +3624,9 @@ specified channel.</p>
</dl>
<dl>
<dt><code>PFUNC</code></dt>
<dd>Pointer to a user supplied callback function. A null pointer uninstalls
<dd>Address of user supplied callback function. A null pointer uninstalls
the current handler. The following arguments are passed <em>by value</em>
to the supplied callback handler.
to the supplied callback handler.
<pre>typedef struct ca_access_rights {
unsigned read_access:1;
unsigned write_access:1;
@@ -3975,8 +3966,8 @@ type.</p>
prints diagnostics to standard out.</p>
<h4>Examples</h4>
<pre>void ca_test_event ();
status = ca_create_subscription ( type, chid, ca_test_event, NULL, NULL );
<pre>void ca_test_event ();
status = ca_create_subscription ( type, chid, ca_test_event, NULL, NULL );
SEVCHK ( status, .... );</pre>
<h4>See Also</h4>
@@ -4010,8 +4001,8 @@ outstanding within them at any given time.</p>
</dl>
<h4>Examples</h4>
<pre>CA_SYNC_GID gid;
status = ca_sg_create ( &amp;gid );
<pre>CA_SYNC_GID gid;
status = ca_sg_create ( &amp;gid );
SEVCHK ( status, Sync group create failed );</pre>
<h4>Returns</h4>
@@ -4049,8 +4040,8 @@ int ca_sg_delete ( CA_SYNC_GID GID );</pre>
</dl>
<h4>Examples</h4>
<pre>CA_SYNC_GID gid;
status = ca_sg_delete ( gid );
<pre>CA_SYNC_GID gid;
status = ca_sg_delete ( gid );
SEVCHK ( status, Sync group delete failed );</pre>
<h4>Returns</h4>
@@ -4161,7 +4152,7 @@ will not block unless additional subsequent requests are made.</p>
</dl>
<h4>Examples</h4>
<pre>CA_SYNC_GID gid;
<pre>CA_SYNC_GID gid;
status = ca_sg_reset(gid);</pre>
<h4>Returns</h4>
@@ -4174,7 +4165,7 @@ status = ca_sg_reset(gid);</pre>
<pre>#include &lt;cadef.h&gt;
int ca_sg_put ( CA_SYNC_GID GID, chtype TYPE,
chid CHID, void *PVALUE );
int ca_sg_array_put ( CA_SYNC_GID GID, chtype TYPE,
int ca_sg_array_put ( CA_SYNC_GID GID, chtype TYPE,
unsigned long COUNT, chid CHID, void *PVALUE );</pre>
<p>Write a value, or array of values, to a channel and increment the outstanding
@@ -4315,7 +4306,7 @@ reissued.</p>
<h3><code><a name="ca_client_status">ca_client_status()</a></code></h3>
<pre>int ca_client_status ( unsigned level );
int ca_context_status ( struct ca_client_context *CONTEXT,
int ca_context_status ( struct ca_client_context *CONTEXT,
unsigned LEVEL );</pre>
<h4>Description</h4>

View File

@@ -69,7 +69,6 @@ LIBSRCS += comQueSend.cpp
LIBSRCS += comBuf.cpp
LIBSRCS += hostNameCache.cpp
LIBSRCS += msgForMultiplyDefinedPV.cpp
LIBSRCS_vxWorks += templateInstances.cpp
LIBRARY=ca

View File

@@ -127,10 +127,21 @@ const char * ca_message_text []
static epicsThreadOnceId caClientContextIdOnce = EPICS_THREAD_ONCE_INIT;
extern "C" void ca_client_exit_handler (void *)
{
if ( caClientContextId ) {
epicsThreadPrivateDelete ( caClientContextId );
caClientContextId = 0;
}
}
// runs once only for each process
extern "C" void ca_init_client_context ( void * )
{
caClientContextId = epicsThreadPrivateCreate ();
if ( caClientContextId ) {
epicsAtExit ( ca_client_exit_handler,0 );
}
}
/*

View File

@@ -1,94 +0,0 @@
/*************************************************************************\
* 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 Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, The Regents of the University of California.
*
*
* Author Jeffrey O. Hill
* johill@lanl.gov
* 505 665 1831
*/
#ifndef autoPtrDestroyh
#define autoPtrDestroyh
template < class T >
class autoPtrDestroy {
public:
autoPtrDestroy ( T * );
~autoPtrDestroy ();
T & operator * () const;
T * operator -> () const;
autoPtrDestroy<T> & operator = ( T * );
T * get () const;
T * release ();
private:
T * p;
// not implemented
autoPtrDestroy<T> & operator = ( const autoPtrDestroy<T> & );
autoPtrDestroy ( const autoPtrDestroy<T> & );
};
template < class T >
inline autoPtrDestroy<T>::autoPtrDestroy ( T *pIn ) :
p ( pIn ) {}
template < class T >
inline autoPtrDestroy<T>::~autoPtrDestroy ()
{
if ( this->p ) {
this->p->destroy ();
}
}
template < class T >
inline T & autoPtrDestroy<T>::operator * () const
{
return * this->p;
}
template < class T >
inline T * autoPtrDestroy<T>::operator -> () const
{
return this->p;
}
template < class T >
inline autoPtrDestroy<T> & autoPtrDestroy<T>::operator = ( T * pIn )
{
if ( this->p ) {
this->p->destroy ();
}
this->p = pIn;
return *this;
}
template < class T >
inline T * autoPtrDestroy<T>::get () const
{
return this->p;
}
template < class T >
inline T * autoPtrDestroy<T>::release ()
{
T *pTmp = this->p;
this->p = 0;
return pTmp;
}
#endif // #ifdef autoPtrDestroyh

View File

@@ -28,7 +28,8 @@
#define CA_VERSION_STRING( MINOR_REVISION ) \
( capStrOfX ( CA_MAJOR_PROTOCOL_REVISION ) "." capStrOfX ( MINOR_REVISION ) )
#define CA_UKN_MINOR_VERSION 0u /* unknown minor version */
#if CA_MAJOR_PROTOCOL_REVISION == 4u
#define CA_MINIMUM_SUPPORTED_VERSION 4u
# define CA_VSUPPORTED(MINOR) ((MINOR)>=CA_MINIMUM_SUPPORTED_VERSION)
# define CA_V41(MINOR) ((MINOR)>=1u)
# define CA_V42(MINOR) ((MINOR)>=2u)
# define CA_V43(MINOR) ((MINOR)>=3u)
@@ -42,35 +43,6 @@
# define CA_V411(MINOR) ((MINOR)>=11u) /* sequence numbers in UDP version command */
# define CA_V412(MINOR) ((MINOR)>=12u) /* TCP-based search requests */
# define CA_V413(MINOR) ((MINOR)>=13u) /* Allow zero length in requests. */
#elif CA_MAJOR_PROTOCOL_REVISION > 4u
# define CA_V41(MINOR) ( 1u )
# define CA_V42(MINOR) ( 1u )
# define CA_V43(MINOR) ( 1u )
# define CA_V44(MINOR) ( 1u )
# define CA_V45(MINOR) ( 1u )
# define CA_V46(MINOR) ( 1u )
# define CA_V47(MINOR) ( 1u )
# define CA_V48(MINOR) ( 1u )
# define CA_V49(MINOR) ( 1u )
# define CA_V410(MINOR) ( 1u )
# define CA_V411(MINOR) ( 1u )
# define CA_V412(MINOR) ( 1u )
# define CA_V413(MINOR) ( 1u )
#else
# define CA_V41(MINOR) ( 0u )
# define CA_V42(MINOR) ( 0u )
# define CA_V43(MINOR) ( 0u )
# define CA_V44(MINOR) ( 0u )
# define CA_V45(MINOR) ( 0u )
# define CA_V46(MINOR) ( 0u )
# define CA_V47(MINOR) ( 0u )
# define CA_V48(MINOR) ( 0u )
# define CA_V49(MINOR) ( 0u )
# define CA_V410(MINOR) ( 0u )
# define CA_V411(MINOR) ( 0u )
# define CA_V412(MINOR) ( 0u )
# define CA_V413(MINOR) ( 0u )
#endif
/*
* These port numbers are only used if the CA repeater and

View File

@@ -159,7 +159,7 @@ ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
this->localPort = htons ( tmpAddr.ia.sin_port );
}
epics_auto_ptr < CallbackGuard > pCBGuard;
std::auto_ptr < CallbackGuard > pCBGuard;
if ( ! enablePreemptiveCallback ) {
pCBGuard.reset ( new CallbackGuard ( this->cbMutex ) );
}

View File

@@ -32,6 +32,7 @@
#include "envDefs.h"
#include "locationException.h"
#include "errlog.h"
#include "epicsExport.h"
#define epicsExportSharedSymbols
#include "addrList.h"
@@ -218,9 +219,15 @@ cac::cac (
throw std::bad_alloc ();
}
freeListInitPvt ( &this->tcpLargeRecvBufFreeList, this->maxRecvBytesTCP, 1 );
if ( ! this->tcpLargeRecvBufFreeList ) {
throw std::bad_alloc ();
int autoMaxBytes;
if(envGetBoolConfigParam(&EPICS_CA_AUTO_ARRAY_BYTES, &autoMaxBytes))
autoMaxBytes = 1;
if(!autoMaxBytes) {
freeListInitPvt ( &this->tcpLargeRecvBufFreeList, this->maxRecvBytesTCP, 1 );
if ( ! this->tcpLargeRecvBufFreeList ) {
throw std::bad_alloc ();
}
}
unsigned bufsPerArray = this->maxRecvBytesTCP / comBuf::capacityBytes ();
if ( bufsPerArray > 1u ) {
@@ -231,9 +238,7 @@ cac::cac (
catch ( ... ) {
osiSockRelease ();
delete [] this->pUserName;
if ( this->tcpSmallRecvBufFreeList ) {
freeListCleanup ( this->tcpSmallRecvBufFreeList );
}
freeListCleanup ( this->tcpSmallRecvBufFreeList );
if ( this->tcpLargeRecvBufFreeList ) {
freeListCleanup ( this->tcpLargeRecvBufFreeList );
}
@@ -260,9 +265,14 @@ cac::cac (
tcpiiu * piiu = NULL;
SearchDestTCP * pdst = new SearchDestTCP ( *this, pNode->addr );
this->registerSearchDest ( guard, * pdst );
/* Initially assume that servers listed in EPICS_CA_NAME_SERVERS support at least minor
* version 11. This causes tcpiiu to send the user and host name authentication
* messages. When the actual Version message is received from the server it will
* be overwrite this assumption.
*/
bool newIIU = findOrCreateVirtCircuit (
guard, pNode->addr, cacChannel::priorityDefault,
piiu, CA_UKN_MINOR_VERSION, pdst );
piiu, 11, pdst );
free ( pNode );
if ( newIIU ) {
piiu->start ( guard );
@@ -318,7 +328,9 @@ cac::~cac ()
}
freeListCleanup ( this->tcpSmallRecvBufFreeList );
freeListCleanup ( this->tcpLargeRecvBufFreeList );
if ( this->tcpLargeRecvBufFreeList ) {
freeListCleanup ( this->tcpLargeRecvBufFreeList );
}
delete [] this->pUserName;

View File

@@ -51,6 +51,7 @@
class netWriteNotifyIO;
class netReadNotifyIO;
class netSubscription;
class tcpiiu;
// used to control access to cac's recycle routines which
// should only be indirectly invoked by CAC when its lock
@@ -193,12 +194,6 @@ public:
const char *pformat, va_list args ) const;
double connectionTimeout ( epicsGuard < epicsMutex > & );
// buffer management
char * allocateSmallBufferTCP ();
void releaseSmallBufferTCP ( char * );
unsigned largeBufferSizeTCP () const;
char * allocateLargeBufferTCP ();
void releaseLargeBufferTCP ( char * );
unsigned maxContiguousFrames ( epicsGuard < epicsMutex > & ) const;
// misc
@@ -355,6 +350,8 @@ private:
cac ( const cac & );
cac & operator = ( const cac & );
friend class tcpiiu;
};
inline const char * cac::userNamePointer () const
@@ -385,35 +382,6 @@ inline void cac::attachToClientCtx ()
this->notify.attachToClientCtx ();
}
inline char * cac::allocateSmallBufferTCP ()
{
// this locks internally
return ( char * ) freeListMalloc ( this->tcpSmallRecvBufFreeList );
}
inline void cac::releaseSmallBufferTCP ( char *pBuf )
{
// this locks internally
freeListFree ( this->tcpSmallRecvBufFreeList, pBuf );
}
inline unsigned cac::largeBufferSizeTCP () const
{
return this->maxRecvBytesTCP;
}
inline char * cac::allocateLargeBufferTCP ()
{
// this locks internally
return ( char * ) freeListMalloc ( this->tcpLargeRecvBufFreeList );
}
inline void cac::releaseLargeBufferTCP ( char *pBuf )
{
// this locks internally
freeListFree ( this->tcpLargeRecvBufFreeList, pBuf );
}
inline unsigned cac::beaconAnomaliesSinceProgramStart (
epicsGuard < epicsMutex > & guard ) const
{

View File

@@ -58,6 +58,7 @@ protected:
channelNode ();
bool isInstalledInServer ( epicsGuard < epicsMutex > & ) const;
bool isConnected ( epicsGuard < epicsMutex > & ) const;
public:
static unsigned getMaxSearchTimerCount ();
private:
enum channelState {

View File

@@ -26,13 +26,14 @@
#ifndef oldAccessh
#define oldAccessh
#include <memory>
#ifdef epicsExportSharedSymbols
# define oldAccessh_restore_epicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include "tsFreeList.h"
#include "epicsMemory.h"
#include "compilerDependencies.h"
#include "osiSock.h"
@@ -402,8 +403,8 @@ private:
epicsEvent ioDone;
epicsEvent callbackThreadActivityComplete;
epicsThreadId createdByThread;
epics_auto_ptr < CallbackGuard > pCallbackGuard;
epics_auto_ptr < cacContext > pServiceContext;
std::auto_ptr < CallbackGuard > pCallbackGuard;
std::auto_ptr < cacContext > pServiceContext;
caExceptionHandler * ca_exception_func;
void * ca_exception_arg;
caPrintfFunc * pVPrintfFunc;

View File

@@ -390,7 +390,7 @@ int epicsShareAPI ca_array_get_callback ( chtype type,
{
caStatus = ECA_ALLOCMEM;
}
catch ( cacChannel::msgBodyCacheTooSmall & ) {
catch ( cacChannel::msgBodyCacheTooSmall ) {
caStatus = ECA_TOLARGE;
}
catch ( ... )

View File

@@ -652,7 +652,7 @@ not follow this pattern, but are still printable strings.
=item [1] R3.15 Channel Access Reference Manual by Jeffrey O. Hill
L<https://epics.anl.gov/base/R3-15/5-docs/CAref.html>
L<http://www.aps.anl.gov/epics/base/R3-15/2-docs/CAref.html>
=back

View File

@@ -58,7 +58,7 @@ Cap5_LIBS = ca Com
Cap5_INCLUDES = -I$(shell $(PERL) ../perlConfig.pl archlib)/CORE
Cap5_CFLAGS = $(shell $(PERL) ../perlConfig.pl ccflags)
CLEANS += Cap5.c
CLEANS += Cap5.c pod2htmd.tmp pod2htmi.tmp
include $(TOP)/configure/RULES

View File

@@ -140,10 +140,6 @@ sub display {
printf " Lo ctrl limit: %g\n", $data->{lower_ctrl_limit};
printf " Hi ctrl limit: %g\n", $data->{upper_ctrl_limit};
}
if (exists $data->{ackt}) {
printf " Ack transients: %s\n", $data->{ackt} ? 'YES' : 'NO';
printf " Ack severity: %s\n", $data->{acks};
}
} else {
my $value = format_number($data, $type);
if ($opt_t) {

View File

@@ -66,6 +66,8 @@ void repeaterSubscribeTimer::shutdown (
epicsTimerNotify::expireStatus repeaterSubscribeTimer::
expire ( const epicsTime & /* currentTime */ )
{
epicsGuard < epicsMutex > guard ( this->stateMutex );
static const unsigned nTriesToMsg = 50;
if ( this->attempts > nTriesToMsg && ! this->once ) {
callbackManager mgr ( this->ctxNotify, this->cbMutex );
@@ -92,12 +94,15 @@ epicsTimerNotify::expireStatus repeaterSubscribeTimer::
void repeaterSubscribeTimer::show ( unsigned /* level */ ) const
{
epicsGuard < epicsMutex > guard ( this->stateMutex );
::printf ( "repeater subscribe timer: attempts=%u registered=%u once=%u\n",
this->attempts, this->registered, this->once );
}
void repeaterSubscribeTimer::confirmNotify ()
{
epicsGuard < epicsMutex > guard ( this->stateMutex );
this->registered = true;
}

View File

@@ -70,6 +70,7 @@ private:
repeaterTimerNotify & iiu;
epicsMutex & cbMutex;
cacContextNotify & ctxNotify;
mutable epicsMutex stateMutex;
unsigned attempts;
bool registered;
bool once;

View File

@@ -24,7 +24,6 @@
#define epicsAssertAuthor "Jeff Hill johill@lanl.gov"
#include "tsMinMax.h"
#include "envDefs.h"
#define epicsExportSharedSymbols

View File

@@ -26,6 +26,9 @@
#include <stdexcept>
#include <string>
#include <stdlib.h>
#include "errlog.h"
#define epicsExportSharedSymbols
@@ -687,7 +690,7 @@ tcpiiu::tcpiiu (
curDataBytes ( 0ul ),
comBufMemMgr ( comBufMemMgrIn ),
cacRef ( cac ),
pCurData ( cac.allocateSmallBufferTCP () ),
pCurData ( (char*) freeListMalloc(this->cacRef.tcpSmallRecvBufFreeList) ),
pSearchDest ( pSearchDestIn ),
mutex ( mutexIn ),
cbMutex ( cbMutexIn ),
@@ -711,9 +714,12 @@ tcpiiu::tcpiiu (
socketHasBeenClosed ( false ),
unresponsiveCircuit ( false )
{
if(!pCurData)
throw std::bad_alloc();
this->sock = epicsSocketCreate ( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if ( this->sock == INVALID_SOCKET ) {
cac.releaseSmallBufferTCP ( this->pCurData );
freeListFree(this->cacRef.tcpSmallRecvBufFreeList, this->pCurData);
char sockErrBuf[64];
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
@@ -1023,11 +1029,14 @@ tcpiiu :: ~tcpiiu ()
// free message body cache
if ( this->pCurData ) {
if ( this->curDataMax == MAX_TCP ) {
this->cacRef.releaseSmallBufferTCP ( this->pCurData );
if ( this->curDataMax <= MAX_TCP ) {
freeListFree(this->cacRef.tcpSmallRecvBufFreeList, this->pCurData);
}
else if ( this->cacRef.tcpLargeRecvBufFreeList ) {
freeListFree(this->cacRef.tcpLargeRecvBufFreeList, this->pCurData);
}
else {
this->cacRef.releaseLargeBufferTCP ( this->pCurData );
free ( this->pCurData );
}
}
}
@@ -1197,18 +1206,46 @@ bool tcpiiu::processIncoming (
// make sure we have a large enough message body cache
//
if ( this->curMsg.m_postsize > this->curDataMax ) {
if ( this->curDataMax == MAX_TCP &&
this->cacRef.largeBufferSizeTCP() >= this->curMsg.m_postsize ) {
char * pBuf = this->cacRef.allocateLargeBufferTCP ();
if ( pBuf ) {
this->cacRef.releaseSmallBufferTCP ( this->pCurData );
this->pCurData = pBuf;
this->curDataMax = this->cacRef.largeBufferSizeTCP ();
assert (this->curMsg.m_postsize > MAX_TCP);
char * newbuf = NULL;
arrayElementCount newsize;
if ( !this->cacRef.tcpLargeRecvBufFreeList ) {
// round size up to multiple of 4K
newsize = ((this->curMsg.m_postsize-1)|0xfff)+1;
if ( this->curDataMax <= MAX_TCP ) {
// small -> large
newbuf = (char*)malloc(newsize);
} else {
// expand large to larger
newbuf = (char*)realloc(this->pCurData, newsize);
}
else {
this->printFormated ( mgr.cbGuard,
"CAC: not enough memory for message body cache (ignoring response message)\n");
} else if ( this->curMsg.m_postsize <= this->cacRef.maxRecvBytesTCP ) {
newbuf = (char*) freeListMalloc(this->cacRef.tcpLargeRecvBufFreeList);
newsize = this->cacRef.maxRecvBytesTCP;
}
if ( newbuf) {
if (this->curDataMax <= MAX_TCP) {
freeListFree(this->cacRef.tcpSmallRecvBufFreeList, this->pCurData );
} else if (this->cacRef.tcpLargeRecvBufFreeList) {
freeListFree(this->cacRef.tcpLargeRecvBufFreeList, this->pCurData );
} else {
// called realloc()
}
this->pCurData = newbuf;
this->curDataMax = newsize;
} else {
this->printFormated ( mgr.cbGuard,
"CAC: not enough memory for message body cache (ignoring response message)\n");
}
}
@@ -1426,7 +1463,7 @@ void tcpiiu::readNotifyRequest ( epicsGuard < epicsMutex > & guard,
}
arrayElementCount maxBytes;
if ( CA_V49 ( this->minorProtocolVersion ) ) {
maxBytes = this->cacRef.largeBufferSizeTCP ();
maxBytes = 0xfffffff0;
}
else {
maxBytes = MAX_TCP;
@@ -1537,7 +1574,7 @@ void tcpiiu::subscriptionRequest (
guard, CA_V413(this->minorProtocolVersion) );
arrayElementCount maxBytes;
if ( CA_V49 ( this->minorProtocolVersion ) ) {
maxBytes = this->cacRef.largeBufferSizeTCP ();
maxBytes = 0xfffffff0;
}
else {
maxBytes = MAX_TCP;
@@ -1584,7 +1621,7 @@ void tcpiiu::subscriptionUpdateRequest (
guard, CA_V413(this->minorProtocolVersion) );
arrayElementCount maxBytes;
if ( CA_V49 ( this->minorProtocolVersion ) ) {
maxBytes = this->cacRef.largeBufferSizeTCP ();
maxBytes = 0xfffffff0;
}
else {
maxBytes = MAX_TCP;

View File

@@ -1,89 +0,0 @@
/*************************************************************************\
* 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 Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
*
*
* L O S A L A M O S
* Los Alamos National Laboratory
* Los Alamos, New Mexico 87545
*
* Copyright, 1986, The Regents of the University of California.
*
*
* Author Jeffrey O. Hill
* johill@lanl.gov
* 505 665 1831
*/
#define epicsExportSharedSymbols
#include "virtualCircuit.h"
#include "bhe.h"
#include "cac.h"
#include "syncGroup.h"
#include "nciu.h"
#include "udpiiu.h"
#include "oldAccess.h"
#include "msgForMultiplyDefinedPV.h"
#include "repeaterClient.h"
#include "hostNameCache.h"
#include "comBuf.h"
#ifdef _MSC_VER
# pragma warning ( push )
# pragma warning ( disable:4660 )
#endif
template class resTable < nciu, chronIntId >;
template class chronIntIdResTable < nciu >;
template class resTable < baseNMIU, chronIntId >;
template class chronIntIdResTable < baseNMIU >;
template class resTable < CASG, chronIntId >;
template class chronIntIdResTable < CASG >;
template class resTable < bhe, inetAddrID >;
template class resTable < tcpiiu, caServerID >;
template class tsFreeList < bhe, 0x100 >;
template class tsFreeList < tcpiiu, 32, epicsMutexNOOP >;
template class tsFreeList < netReadNotifyIO, 1024, epicsMutexNOOP >;
template class tsFreeList < netWriteNotifyIO, 1024, epicsMutexNOOP >;
template class tsFreeList < netSubscription, 1024, epicsMutexNOOP >;
template class tsFreeList < CASG, 128, epicsMutexNOOP >;
template class tsFreeList < syncGroupReadNotify, 128, epicsMutexNOOP >;
template class tsFreeList < syncGroupWriteNotify, 128, epicsMutexNOOP >;
template class tsFreeList < comBuf, 0x20 >;
template class tsFreeList < getCallback, 1024, epicsMutexNOOP >;
template class tsFreeList < getCopy, 1024, epicsMutexNOOP >;
template class tsFreeList < msgForMultiplyDefinedPV, 16 >;
template class tsFreeList < nciu, 1024, epicsMutexNOOP>;
template class tsFreeList < oldChannelNotify, 1024, epicsMutexNOOP >;
template class tsFreeList < oldSubscription, 1024, epicsMutexNOOP >;
template class tsFreeList < putCallback, 1024, epicsMutexNOOP >;
template class tsFreeList < repeaterClient, 0x20 >;
template class epicsSingleton < localHostName >;
template class epics_auto_ptr < epics_auto_ptr < class searchTimer >, eapt_array >;
template unsigned comBuf :: push ( const double * pValue, unsigned nElem );
template unsigned comBuf :: push ( const float * pValue, unsigned nElem );
template unsigned comBuf :: push ( const int * pValue, unsigned nElem );
template unsigned comBuf :: push ( const short * pValue, unsigned nElem );
template comBuf :: popStatus comBuf :: pop ( unsigned int & returnVal );
template comBuf :: popStatus comBuf :: pop ( unsigned short & returnVal );
template comBuf :: popStatus comBuf :: pop ( unsigned char & returnVal );
template void WireSet ( float const &, unsigned char * );
template void WireSet ( int const &, unsigned char * );
template void WireSet ( short const &, unsigned char * );
template void ca_client_context :: whenThereIsAnExceptionDestroySyncGroupIO
(epicsGuard < epicsMutex > &, syncGroupWriteNotify & );
template void ca_client_context :: whenThereIsAnExceptionDestroySyncGroupIO
( epicsGuard < epicsMutex > &, syncGroupReadNotify & );
#ifdef _MSC_VER
# pragma warning ( pop )
#endif

View File

@@ -8,7 +8,7 @@
* Copyright (c) 2002 Berliner Elektronenspeicherringgesellschaft fuer
* Synchrotronstrahlung.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
@@ -419,7 +419,7 @@ int main (int argc, char *argv[])
if (argc > optind+1) {
for (i = optind + 1; i < argc; i++) {
strcat(cbuf, " ");
strcat(cbuf, argv[i]);
strcat(cbuf, argv[i]);
}
}
@@ -530,11 +530,6 @@ int main (int argc, char *argv[])
/* Use standard put with defined timeout */
result = ca_array_put (dbrType, count, pvs[0].chid, pbuf);
}
if (result != ECA_NORMAL) {
fprintf(stderr, "Error from put operation: %s\n", ca_message(result));
return 1;
}
result = ca_pend_io(caTimeout);
if (result == ECA_TIMEOUT) {
fprintf(stderr, "Write operation timed out: Data was not written.\n");
@@ -550,7 +545,7 @@ int main (int argc, char *argv[])
}
if (result != ECA_NORMAL) {
fprintf(stderr, "Error occured writing data: %s\n", ca_message(result));
fprintf(stderr, "Error occured writing data.\n");
return 1;
}

View File

@@ -79,14 +79,14 @@ static void sprint_long (char *ret, dbr_long_t val, IntFormatT outType)
}
else {
const char *fmt[4] = { /* Order must match the enum IntFormatT */
"%d" /* dec */,
"0" /* bin and val is 0 */,
"0o%o" /* oct */,
"0x%X" /* hex */
"%ld" /* dec */,
"0" /* bin, val is 0 */,
"0o%lo" /* oct */,
"0x%lX" /* hex */
};
/* dbr_long_t is actually an int on all supported platforms */
sprintf(ret, fmt[outType], (int) val);
/* Formats have long modifier, pass value as a long */
sprintf(ret, fmt[outType], (long) val);
}
}
@@ -414,12 +414,6 @@ char *dbr2str (const void *value, unsigned type)
ptsNewS = &((struct TYPE *)value)->stamp; \
ptsNewC = &tsNow; \
\
if (!tsInitS) \
{ \
tsFirst = *ptsNewS; \
tsInitS = 1; \
} \
\
switch (tsType) { \
case relative: \
ptsRefC = &tsStart; \
@@ -512,6 +506,12 @@ void print_time_val_sts (pv* pv, unsigned long reqElems)
epicsTimeGetCurrent(&tsNow);
epicsTimeToStrftime(timeText, TIMETEXTLEN, timeFormatStr, &tsNow);
if (!tsInitS)
{
tsFirst = tsNow;
tsInitS = 1;
}
if (pv->nElems <= 1 && fieldSeparator == ' ') printf("%-30s", pv->name);
else printf("%s", pv->name);
printf("%c", fieldSeparator);

View File

@@ -64,6 +64,52 @@ const udpiiu::pProtoStubUDP udpiiu::udpJumpTableCAC [] =
&udpiiu::repeaterAckAction,
};
static
double getMaxPeriod()
{
double maxPeriod = maxSearchPeriodDefault;
if ( envGetConfigParamPtr ( & EPICS_CA_MAX_SEARCH_PERIOD ) ) {
long longStatus = envGetDoubleConfigParam (
& EPICS_CA_MAX_SEARCH_PERIOD, & maxPeriod );
if ( ! longStatus ) {
if ( maxPeriod < maxSearchPeriodLowerLimit ) {
epicsPrintf ( "\"%s\" out of range (low)\n",
EPICS_CA_MAX_SEARCH_PERIOD.name );
maxPeriod = maxSearchPeriodLowerLimit;
epicsPrintf ( "Setting \"%s\" = %f seconds\n",
EPICS_CA_MAX_SEARCH_PERIOD.name, maxPeriod );
}
}
else {
epicsPrintf ( "EPICS \"%s\" wasnt a real number\n",
EPICS_CA_MAX_SEARCH_PERIOD.name );
epicsPrintf ( "Setting \"%s\" = %f seconds\n",
EPICS_CA_MAX_SEARCH_PERIOD.name, maxPeriod );
}
}
return maxPeriod;
}
static
unsigned getNTimers(double maxPeriod)
{
unsigned nTimers = static_cast < unsigned > ( 1.0 + log ( maxPeriod / minRoundTripEstimate ) / log ( 2.0 ) );
if ( nTimers > channelNode::getMaxSearchTimerCount () ) {
nTimers = channelNode::getMaxSearchTimerCount ();
epicsPrintf ( "\"%s\" out of range (high)\n",
EPICS_CA_MAX_SEARCH_PERIOD.name );
epicsPrintf ( "Setting \"%s\" = %f seconds\n",
EPICS_CA_MAX_SEARCH_PERIOD.name,
(1<<(nTimers-1)) * minRoundTripEstimate );
}
return nTimers;
}
//
// udpiiu::udpiiu ()
//
@@ -85,14 +131,15 @@ udpiiu::udpiiu (
repeaterSubscribeTmr (
m_repeaterTimerNotify, timerQueue, cbMutexIn, ctxNotifyIn ),
govTmr ( *this, timerQueue, cacMutexIn ),
maxPeriod ( maxSearchPeriodDefault ),
maxPeriod ( getMaxPeriod() ),
rtteMean ( minRoundTripEstimate ),
rtteMeanDev ( 0 ),
cacRef ( cac ),
cbMutex ( cbMutexIn ),
cacMutex ( cacMutexIn ),
nTimers ( getNTimers(maxPeriod) ),
ppSearchTmr ( nTimers ),
nBytesInXmitBuf ( 0 ),
nTimers ( 0 ),
beaconAnomalyTimerIndex ( 0 ),
sequenceNumber ( 0 ),
lastReceivedSeqNo ( 0 ),
@@ -104,45 +151,13 @@ udpiiu::udpiiu (
lastReceivedSeqNoIsValid ( false )
{
cacGuard.assertIdenticalMutex ( cacMutex );
if ( envGetConfigParamPtr ( & EPICS_CA_MAX_SEARCH_PERIOD ) ) {
long longStatus = envGetDoubleConfigParam (
& EPICS_CA_MAX_SEARCH_PERIOD, & this->maxPeriod );
if ( ! longStatus ) {
if ( this->maxPeriod < maxSearchPeriodLowerLimit ) {
epicsPrintf ( "\"%s\" out of range (low)\n",
EPICS_CA_MAX_SEARCH_PERIOD.name );
this->maxPeriod = maxSearchPeriodLowerLimit;
epicsPrintf ( "Setting \"%s\" = %f seconds\n",
EPICS_CA_MAX_SEARCH_PERIOD.name, this->maxPeriod );
}
}
else {
epicsPrintf ( "EPICS \"%s\" wasnt a real number\n",
EPICS_CA_MAX_SEARCH_PERIOD.name );
epicsPrintf ( "Setting \"%s\" = %f seconds\n",
EPICS_CA_MAX_SEARCH_PERIOD.name, this->maxPeriod );
}
}
double powerOfTwo = log ( this->maxPeriod / minRoundTripEstimate ) / log ( 2.0 );
this->nTimers = static_cast < unsigned > ( powerOfTwo + 1.0 );
if ( this->nTimers > channelNode::getMaxSearchTimerCount () ) {
this->nTimers = channelNode::getMaxSearchTimerCount ();
epicsPrintf ( "\"%s\" out of range (high)\n",
EPICS_CA_MAX_SEARCH_PERIOD.name );
epicsPrintf ( "Setting \"%s\" = %f seconds\n",
EPICS_CA_MAX_SEARCH_PERIOD.name,
(1<<(this->nTimers-1)) * minRoundTripEstimate );
}
powerOfTwo = log ( beaconAnomalySearchPeriod / minRoundTripEstimate ) / log ( 2.0 );
double powerOfTwo = log ( beaconAnomalySearchPeriod / minRoundTripEstimate ) / log ( 2.0 );
this->beaconAnomalyTimerIndex = static_cast < unsigned > ( powerOfTwo + 1.0 );
if ( this->beaconAnomalyTimerIndex >= this->nTimers ) {
this->beaconAnomalyTimerIndex = this->nTimers - 1;
}
this->ppSearchTmr.reset ( new epics_auto_ptr < class searchTimer > [ this->nTimers ] );
for ( unsigned i = 0; i < this->nTimers; i++ ) {
this->ppSearchTmr[i].reset (
new searchTimer ( *this, timerQueue, i, cacMutexIn,
@@ -165,7 +180,7 @@ udpiiu::udpiiu (
#ifdef IP_ADD_MEMBERSHIP
{
osiSockOptMcastLoop_t flag = 1;
int flag = 1;
if ( setsockopt ( this->sock, IPPROTO_IP, IP_MULTICAST_LOOP,
(char *) &flag, sizeof ( flag ) ) == -1 ) {
char sockErrBuf[64];
@@ -176,6 +191,22 @@ udpiiu::udpiiu (
}
#endif
#ifdef IP_MULTICAST_TTL
{
int ttl;
long val;
if(envGetLongConfigParam(&EPICS_CA_MCAST_TTL, &val))
val =1;
ttl = val;
if ( setsockopt(this->sock, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl))) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
errlogPrintf("CAC: failed to set mcast ttl %d\n", ttl);
}
}
#endif
int boolValue = true;
int status = setsockopt ( this->sock, SOL_SOCKET, SO_BROADCAST,
(char *) &boolValue, sizeof ( boolValue ) );

View File

@@ -25,6 +25,8 @@
#ifndef udpiiuh
#define udpiiuh
#include <memory>
#ifdef epicsExportSharedSymbols
# define udpiiuh_accessh_epicsExportSharedSymbols
# undef epicsExportSharedSymbols
@@ -32,9 +34,7 @@
#include "osiSock.h"
#include "epicsThread.h"
#include "epicsMemory.h"
#include "epicsTime.h"
#include "tsMinMax.h"
#include "tsDLList.h"
#ifdef udpiiuh_accessh_epicsExportSharedSymbols
@@ -160,15 +160,24 @@ private:
repeaterSubscribeTimer repeaterSubscribeTmr;
disconnectGovernorTimer govTmr;
tsDLList < SearchDest > _searchDestList;
double maxPeriod;
const double maxPeriod;
double rtteMean;
double rtteMeanDev;
cac & cacRef;
epicsMutex & cbMutex;
epicsMutex & cacMutex;
epics_auto_ptr < epics_auto_ptr < class searchTimer >, eapt_array > ppSearchTmr;
const unsigned nTimers;
struct SearchArray {
typedef std::auto_ptr <searchTimer> value_type;
value_type *arr;
SearchArray(size_t n) : arr(new value_type[n]) {}
~SearchArray() { delete[] arr; }
value_type& operator[](size_t i) const { return arr[i]; }
private:
SearchArray(const SearchArray&);
SearchArray& operator=(const SearchArray&);
} ppSearchTmr;
unsigned nBytesInXmitBuf;
unsigned nTimers;
unsigned beaconAnomalyTimerIndex;
ca_uint32_t sequenceNumber;
ca_uint32_t lastReceivedSeqNo;

View File

@@ -25,9 +25,7 @@
#ifndef virtualCircuith
#define virtualCircuith
#include "epicsMemory.h"
#include "tsDLList.h"
#include "tsMinMax.h"
#include "comBuf.h"
#include "caServerID.h"

View File

@@ -53,7 +53,6 @@ LIBSRCS += outBuf.cc
LIBSRCS += casCtx.cc
LIBSRCS += casEventMask.cc
LIBSRCS += ioBlocked.cc
LIBSRCS += casBufferFactory.cc
LIBSRCS += pvExistReturn.cc
LIBSRCS += pvAttachReturn.cc
LIBSRCS += caNetAddr.cc
@@ -74,13 +73,12 @@ LIBSRCS += casStreamIO.cc
LIBSRCS += ipIgnoreEntry.cc
# There is a bug in some vxWorks compilers that these work around:
ifeq ($(VXWORKS_VERSION)$(filter -mcpu=604,$(ARCH_DEP_CFLAGS)), 6.6-mcpu=604)
casDGIntfOS_CXXFLAGS = -fno-inline
casStreamOS_CXXFLAGS = -fno-inline
ifeq ($(VX_GNU_VERSION), 4.1.2)
casStreamOS_CXXFLAGS_vxWorks-ppc604_altivec = -O0
casStreamOS_CXXFLAGS_vxWorks-ppc604_long = -O0
casStreamOS_CXXFLAGS_vxWorks-ppc604 = -O0
endif
LIBSRCS_vxWorks += templateInstances.cpp
LIBRARY = cas
cas_LIBS = ca gdd Com
cas_SYS_LIBS_WIN32 = ws2_32

View File

@@ -13,7 +13,7 @@
//
#include "directoryServer.h"
#include "tsMinMax.h"
#include "epicsAlgorithm.h"
const pvInfo *pvInfo::pFirst;
@@ -128,7 +128,7 @@ pvExistReturn directoryServer::pvExistTest
}
else {
size_t diff = pLastStr-pPVName;
diff = tsMin (diff, sizeof(pvNameBuf)-1);
diff = epicsMin (diff, sizeof(pvNameBuf)-1);
memcpy (pvNameBuf, pPVName, diff);
pvNameBuf[diff] = '\0';
pLastStr = pvNameBuf;

View File

@@ -1,104 +0,0 @@
/*************************************************************************\
* 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 Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author Jeffrey O. Hill
* johill@lanl.gov
* 505 665 1831
*/
#include <new>
#include "envDefs.h"
#include "freeList.h"
#include "errlog.h"
#define epicsExportSharedSymbols
#include "clientBufMemoryManager.h"
#include "caProto.h"
casBufferFactory::casBufferFactory () :
smallBufFreeList ( 0 ), largeBufFreeList ( 0 ), largeBufferSizePriv ( 0u )
{
long maxBytesAsALong;
long status = envGetLongConfigParam ( & EPICS_CA_MAX_ARRAY_BYTES, & maxBytesAsALong );
if ( status || maxBytesAsALong < 0 ) {
errlogPrintf ( "cas: EPICS_CA_MAX_ARRAY_BYTES was not a positive integer\n" );
this->largeBufferSizePriv = MAX_TCP;
}
else {
/* allow room for the protocol header so that they get the array size they requested */
static const unsigned headerSize = sizeof ( caHdr ) + 2 * sizeof ( ca_uint32_t );
ca_uint32_t maxBytes = ( unsigned ) maxBytesAsALong;
if ( maxBytes < 0xffffffff - headerSize ) {
maxBytes += headerSize;
}
else {
maxBytes = 0xffffffff;
}
if ( maxBytes < MAX_TCP ) {
errlogPrintf ( "cas: EPICS_CA_MAX_ARRAY_BYTES was rounded up to %u\n", MAX_TCP );
this->largeBufferSizePriv = MAX_TCP;
}
else {
this->largeBufferSizePriv = maxBytes;
}
}
freeListInitPvt ( & this->smallBufFreeList, MAX_MSG_SIZE, 8 );
freeListInitPvt ( & this->largeBufFreeList, this->largeBufferSizePriv, 1 );
}
casBufferFactory::~casBufferFactory ()
{
freeListCleanup ( this->smallBufFreeList );
freeListCleanup ( this->largeBufFreeList );
}
unsigned casBufferFactory::smallBufferSize () const
{
return MAX_MSG_SIZE;
}
char * casBufferFactory::newSmallBuffer ()
{
void * pBuf = freeListCalloc ( this->smallBufFreeList );
if ( ! pBuf ) {
throw std::bad_alloc();
}
return static_cast < char * > ( pBuf );
}
void casBufferFactory::destroySmallBuffer ( char * pBuf )
{
if ( pBuf ) {
freeListFree ( this->smallBufFreeList, pBuf );
}
}
unsigned casBufferFactory::largeBufferSize () const
{
return this->largeBufferSizePriv;
}
char * casBufferFactory::newLargeBuffer ()
{
void * pBuf = freeListCalloc ( this->largeBufFreeList );
if ( ! pBuf ) {
throw std::bad_alloc();
}
return static_cast < char * > ( pBuf );
}
void casBufferFactory::destroyLargeBuffer ( char * pBuf )
{
if ( pBuf ) {
freeListFree ( this->largeBufFreeList, pBuf );
}
}

View File

@@ -5,7 +5,7 @@
* Operator of Los Alamos National Laboratory.
* EPICS BASE Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author Jeffrey O. Hill
@@ -30,9 +30,9 @@ casDGClient::pCASMsgHandler const casDGClient::msgHandlers[] =
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::searchAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::searchAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
@@ -51,7 +51,7 @@ casDGClient::pCASMsgHandler const casDGClient::msgHandlers[] =
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::echoAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
@@ -64,9 +64,9 @@ casDGClient::pCASMsgHandler const casDGClient::msgHandlers[] =
//
casDGClient::casDGClient ( caServerI & serverIn, clientBufMemoryManager & mgrIn ) :
casCoreClient ( serverIn ),
in ( *this, mgrIn, MAX_UDP_RECV + sizeof ( cadg ) ),
in ( *this, mgrIn, MAX_UDP_RECV + sizeof ( cadg ) ),
out ( *this, mgrIn ),
seqNoOfReq ( 0 ),
seqNoOfReq ( 0 ),
minor_version_number ( 0 )
{
}
@@ -92,12 +92,12 @@ void casDGClient::destroy()
//
void casDGClient::show (unsigned level) const
{
printf ( "casDGClient at %p\n",
static_cast <const void *> ( this ) );
printf ( "casDGClient at %p\n",
static_cast <const void *> ( this ) );
if (level>=1u) {
char buf[64];
this->hostName (buf, sizeof(buf));
printf ("Client Host=%s\n", buf);
printf ("Client Host=%s\n", buf);
this->casCoreClient::show ( level - 1u );
this->in.show ( level - 1u );
this->out.show ( level - 1u );
@@ -111,11 +111,13 @@ caStatus casDGClient::uknownMessageAction ()
{
const caHdrLargeArray * mp = this->ctx.getMsg();
char pHostName[64u];
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
if ( this->getCAS().getDebugLevel() > 3u ) {
char pHostName[64u];
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
"bad request code=%u in DG\n", mp->m_cmmd );
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
"bad request code=%u in DG\n", mp->m_cmmd );
}
return S_cas_badProtocol;
}
@@ -129,13 +131,23 @@ caStatus casDGClient::searchAction()
const char *pChanName = static_cast <char * > ( this->ctx.getData() );
caStatus status;
if (!CA_VSUPPORTED(mp->m_count)) {
if ( this->getCAS().getDebugLevel() > 3u ) {
char pHostName[64u];
this->hostName ( pHostName, sizeof ( pHostName ) );
printf ( "\"%s\" is searching for \"%s\" but is too old\n",
pHostName, pChanName );
}
return S_cas_badProtocol;
}
//
// check the sanity of the message
//
if ( mp->m_postsize <= 1 ) {
char pHostName[64u];
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
"empty PV name extension in UDP search request?\n" );
return S_cas_success;
}
@@ -143,19 +155,19 @@ caStatus casDGClient::searchAction()
if ( pChanName[0] == '\0' ) {
char pHostName[64u];
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
"zero length PV name in UDP search request?\n" );
return S_cas_success;
}
// check for an unterminated string before calling server tool
// by searching backwards through the string (some early versions
// by searching backwards through the string (some early versions
// of the client library might not be setting the pad bytes to nill)
for ( unsigned i = mp->m_postsize-1; pChanName[i] != '\0'; i-- ) {
if ( i <= 1 ) {
char pHostName[64u];
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
"unterminated PV name in UDP search request?\n" );
return S_cas_success;
}
@@ -164,7 +176,7 @@ caStatus casDGClient::searchAction()
if ( this->getCAS().getDebugLevel() > 6u ) {
char pHostName[64u];
this->hostName ( pHostName, sizeof ( pHostName ) );
printf ( "\"%s\" is searching for \"%s\"\n",
printf ( "\"%s\" is searching for \"%s\"\n",
pHostName, pChanName );
}
@@ -183,7 +195,7 @@ caStatus casDGClient::searchAction()
// ask the server tool if this PV exists
//
this->userStartedAsyncIO = false;
pvExistReturn pver =
pvExistReturn pver =
this->getCAS()->pvExistTest ( this->ctx, this->lastRecvAddr, pChanName );
//
@@ -193,7 +205,7 @@ caStatus casDGClient::searchAction()
//
if ( this->userStartedAsyncIO ) {
if ( pver.getStatus() != pverAsyncCompletion ) {
errMessage (S_cas_badParameter,
errMessage (S_cas_badParameter,
"- assuming asynch IO status from caServer::pvExistTest()");
}
status = S_cas_success;
@@ -212,13 +224,13 @@ caStatus casDGClient::searchAction()
break;
case pverAsyncCompletion:
errMessage (S_cas_badParameter,
errMessage (S_cas_badParameter,
"- unexpected asynch IO status from caServer::pvExistTest() ignored");
status = S_cas_success;
break;
default:
errMessage (S_cas_badParameter,
errMessage (S_cas_badParameter,
"- invalid return from caServer::pvExistTest() ignored");
status = S_cas_success;
break;
@@ -230,18 +242,18 @@ caStatus casDGClient::searchAction()
//
// caStatus casDGClient::searchResponse()
//
caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
const pvExistReturn & retVal )
{
caStatus status;
if ( retVal.getStatus() != pverExistsHere ) {
return S_cas_success;
}
//
// starting with V4.1 the count field is used (abused)
// by the client to store the minor version number of
// by the client to store the minor version number of
// the client.
//
// Old versions expect alloc of channel in response
@@ -250,8 +262,8 @@ caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
if ( !CA_V44(msg.m_count) ) {
char pName[64u];
this->hostName (pName, sizeof (pName));
errlogPrintf (
"client \"%s\" using EPICS R3.11 CA connect protocol was ignored\n",
errlogPrintf (
"client \"%s\" using EPICS R3.11 CA connect protocol was ignored\n",
pName);
//
// old connect protocol was dropped when the
@@ -264,19 +276,19 @@ caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
}
//
// cid field is abused to carry the IP
// cid field is abused to carry the IP
// address in CA_V48 or higher
// (this allows a CA servers to serve
// as a directory service)
//
// data type field is abused to carry the IP
// data type field is abused to carry the IP
// port number here CA_V44 or higher
// (this allows multiple CA servers on one
// host)
//
ca_uint32_t serverAddr;
ca_uint16_t serverPort;
if ( CA_V48( msg.m_count ) ) {
if ( CA_V48( msg.m_count ) ) {
struct sockaddr_in ina;
if ( retVal.addrIsValid() ) {
caNetAddr addr = retVal.getAddr();
@@ -296,7 +308,7 @@ caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
ina = addr.getSockIP();
//
// We dont fill in the servers address here
// because the server was not bound to a particular
// because the server was not bound to a particular
// interface, and we would need to waste CPU performing
// the following steps to determine the interface that
// will be used:
@@ -318,24 +330,24 @@ caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
serverAddr = ~0U;
serverPort = ntohs ( inetAddr.sin_port );
}
ca_uint16_t * pMinorVersion;
epicsGuard < epicsMutex > guard ( this->mutex );
status = this->out.copyInHeader ( CA_PROTO_SEARCH,
sizeof ( *pMinorVersion ), serverPort, 0,
serverAddr, msg.m_available,
status = this->out.copyInHeader ( CA_PROTO_SEARCH,
sizeof ( *pMinorVersion ), serverPort, 0,
serverAddr, msg.m_available,
reinterpret_cast <void **> ( &pMinorVersion ) );
//
// Starting with CA V4.1 the minor version number
// is appended to the end of each search reply.
// This value is ignored by earlier clients.
// This value is ignored by earlier clients.
//
if ( status == S_cas_success ) {
AlignedWireRef < epicsUInt16 > tmp ( *pMinorVersion );
tmp = CA_MINOR_PROTOCOL_REVISION;
this->out.commitMsg ();
}
return status;
}
@@ -362,6 +374,15 @@ caStatus casDGClient::versionAction ()
{
const caHdrLargeArray * mp = this->ctx.getMsg();
if (!CA_VSUPPORTED(mp->m_count)) {
if ( this->getCAS().getDebugLevel() > 3u ) {
char pHostName[64u];
this->hostName ( pHostName, sizeof ( pHostName ) );
printf ( "\"%s\" is too old\n",
pHostName );
}
return S_cas_badProtocol;
}
if ( mp->m_count != 0 ) {
this->minor_version_number = static_cast <ca_uint16_t> ( mp->m_count );
if ( CA_V411 ( mp->m_count ) ) {
@@ -404,8 +425,8 @@ void casDGClient::sendBeacon ( ca_uint32_t beaconNumber )
//
// casDGClient::xSend()
//
outBufClient::flushCondition casDGClient::xSend ( char *pBufIn,
bufSizeT nBytesToSend, bufSizeT & nBytesSent )
outBufClient::flushCondition casDGClient::xSend ( char *pBufIn,
bufSizeT nBytesToSend, bufSizeT & nBytesSent )
{
bufSizeT totalBytes = 0;
while ( totalBytes < nBytesToSend ) {
@@ -418,7 +439,7 @@ outBufClient::flushCondition casDGClient::xSend ( char *pBufIn,
unsigned sizeDG = pHdr->cadg_nBytes - sizeof ( *pHdr );
if ( pHdr->cadg_addr.isValid() ) {
outBufClient::flushCondition stat =
outBufClient::flushCondition stat =
this->osdSend ( pDG, sizeDG, pHdr->cadg_addr );
if ( stat != outBufClient::flushProgress ) {
break;
@@ -455,7 +476,7 @@ inBufClient::fillCondition casDGClient::xRecv (char *pBufIn, bufSizeT nBytesToRe
while (pAfter-pCurBuf >= static_cast<int>(MAX_UDP_RECV+sizeof(cadg))) {
pHdr = reinterpret_cast < cadg * > ( pCurBuf );
stat = this->osdRecv ( reinterpret_cast < char * > ( pHdr + 1 ),
stat = this->osdRecv ( reinterpret_cast < char * > ( pHdr + 1 ),
MAX_UDP_RECV, parm, nDGBytesRecv, pHdr->cadg_addr);
if (stat==casFillProgress) {
pHdr->cadg_nBytes = nDGBytesRecv + sizeof(*pHdr);
@@ -487,9 +508,9 @@ inBufClient::fillCondition casDGClient::xRecv (char *pBufIn, bufSizeT nBytesToRe
// this results in many small UDP frames which unfortunately
// isnt particularly efficient
//
caStatus casDGClient::asyncSearchResponse (
caStatus casDGClient::asyncSearchResponse (
epicsGuard < casClientMutex > &, const caNetAddr & outAddr,
const caHdrLargeArray & msg, const pvExistReturn & retVal,
const caHdrLargeArray & msg, const pvExistReturn & retVal,
ca_uint16_t protocolRevision, ca_uint32_t sequenceNumber )
{
if ( retVal.getStatus() != pverExistsHere ) {
@@ -497,7 +518,7 @@ caStatus casDGClient::asyncSearchResponse (
}
void * pRaw;
const outBufCtx outctx = this->out.pushCtx
const outBufCtx outctx = this->out.pushCtx
( sizeof(cadg), MAX_UDP_SEND, pRaw );
if ( outctx.pushResult() != outBufCtx::pushCtxSuccess ) {
return S_cas_sendBlocked;
@@ -533,8 +554,8 @@ caStatus casDGClient::processDG ()
{
bufSizeT bytesLeft;
caStatus status;
status = S_cas_success;
status = S_cas_success;
while ( ( bytesLeft = this->in.bytesPresent() ) ) {
bufSizeT dgInBytesConsumed;
const cadg * pReqHdr = reinterpret_cast < cadg * > ( this->in.msgPtr () );
@@ -561,9 +582,9 @@ caStatus casDGClient::processDG ()
// insert version header at the start of the reply message
this->sendVersion ();
cadg * pRespHdr = static_cast < cadg * > ( pRaw );
//
// select the next DG in the input stream and start processing it
//
@@ -593,7 +614,7 @@ caStatus casDGClient::processDG ()
// a) it used all of the incoming DG or
// b) it used all of the outgoing DG
//
// In either case commit the DG to the protocol stream and
// In either case commit the DG to the protocol stream and
// release the send lock
//
// if there are not additional messages passed the version header
@@ -644,11 +665,6 @@ caStatus casDGClient::processDG ()
if ( status != S_cas_success ) {
break;
}
if ( this->in.bytesPresent () > 0 && dgInBytesConsumed == 0 && status == S_cas_success ) {
this->in.removeMsg ( this->in.bytesPresent() );
}
}
return status;
}
@@ -689,7 +705,7 @@ void casDGClient::hostName ( char *pBufIn, unsigned bufSizeIn ) const
void casDGClient::sendVersion ()
{
epicsGuard < epicsMutex > guard ( this->mutex );
caStatus status = this->out.copyInHeader ( CA_PROTO_VERSION, 0,
caStatus status = this->out.copyInHeader ( CA_PROTO_VERSION, 0,
0, CA_MINOR_PROTOCOL_REVISION, 0, 0, 0 );
if ( ! status ) {
this->out.commitMsg ();
@@ -784,8 +800,8 @@ caStatus casDGClient::processMsg ()
msgTmp.m_available = AlignedWireRef < epicsUInt32 > ( smallHdr.m_available );
if ( payloadSize & 0x7 ) {
status = this->sendErr (
& msgTmp, invalidResID, ECA_INTERNAL,
status = this->sendErr (
& msgTmp, invalidResID, ECA_INTERNAL,
"CAS: Datagram request wasn't 8 byte aligned" );
this->in.removeMsg ( bytesLeft );
break;
@@ -794,7 +810,7 @@ caStatus casDGClient::processMsg ()
msgSize = hdrSize + payloadSize;
if ( bytesLeft < msgSize ) {
if ( msgSize > this->in.bufferSize() ) {
status = this->sendErr ( & msgTmp, invalidResID, ECA_TOLARGE,
status = this->sendErr ( & msgTmp, invalidResID, ECA_TOLARGE,
"client's request didnt fit within the CA server's message buffer" );
this->in.removeMsg ( bytesLeft );
}
@@ -806,7 +822,7 @@ caStatus casDGClient::processMsg ()
if ( this->getCAS().getDebugLevel() > 5u ) {
char pHostName[64u];
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
caServerI::dumpMsg ( pHostName, "?",
caServerI::dumpMsg ( pHostName, "?",
& msgTmp, rawMP + hdrSize, 0 );
}
@@ -814,7 +830,7 @@ caStatus casDGClient::processMsg ()
//
// Reset the context to the default
// (guarantees that previous message does not get mixed
// (guarantees that previous message does not get mixed
// up with the current message)
//
this->ctx.setChannel ( NULL );
@@ -841,16 +857,16 @@ caStatus casDGClient::processMsg ()
}
catch ( std::exception & except ) {
this->in.removeMsg ( this->in.bytesPresent() );
this->sendErr (
this->ctx.getMsg(), invalidResID, ECA_INTERNAL,
this->sendErr (
this->ctx.getMsg(), invalidResID, ECA_INTERNAL,
"C++ exception \"%s\" in CA circuit server",
except.what () );
status = S_cas_internal;
}
catch (...) {
this->in.removeMsg ( this->in.bytesPresent() );
this->sendErr (
this->ctx.getMsg(), invalidResID, ECA_INTERNAL,
this->sendErr (
this->ctx.getMsg(), invalidResID, ECA_INTERNAL,
"unexpected C++ exception in CA datagram server" );
status = S_cas_internal;
}
@@ -859,9 +875,9 @@ caStatus casDGClient::processMsg ()
}
//
// casDGClient::sendErr()
// casDGClient::sendErr()
//
caStatus casDGClient::sendErr ( const caHdrLargeArray *curp,
caStatus casDGClient::sendErr ( const caHdrLargeArray *curp,
ca_uint32_t cid, const int reportedStatus, const char *pformat, ... )
{
unsigned stringSize;
@@ -885,14 +901,14 @@ caStatus casDGClient::sendErr ( const caHdrLargeArray *curp,
}
unsigned hdrSize = sizeof ( caHdr );
if ( ( curp->m_postsize >= 0xffff || curp->m_count >= 0xffff ) &&
if ( ( curp->m_postsize >= 0xffff || curp->m_count >= 0xffff ) &&
CA_V49( this->minor_version_number ) ) {
hdrSize += 2 * sizeof ( ca_uint32_t );
}
caHdr * pReqOut;
epicsGuard < epicsMutex > guard ( this->mutex );
caStatus status = this->out.copyInHeader ( CA_PROTO_ERROR,
caStatus status = this->out.copyInHeader ( CA_PROTO_ERROR,
hdrSize + stringSize, 0, 0, cid, reportedStatus,
reinterpret_cast <void **> ( & pReqOut ) );
if ( ! status ) {
@@ -902,7 +918,7 @@ caStatus casDGClient::sendErr ( const caHdrLargeArray *curp,
* copy back the request protocol
* (in network byte order)
*/
if ( ( curp->m_postsize >= 0xffff || curp->m_count >= 0xffff ) &&
if ( ( curp->m_postsize >= 0xffff || curp->m_count >= 0xffff ) &&
CA_V49( this->minor_version_number ) ) {
ca_uint32_t *pLW = ( ca_uint32_t * ) ( pReqOut + 1 );
pReqOut->m_cmmd = htons ( curp->m_cmmd );
@@ -947,7 +963,7 @@ caStatus casDGClient::echoAction ()
void * pPayloadOut;
epicsGuard < epicsMutex > guard ( this->mutex );
caStatus status = this->out.copyInHeader ( mp->m_cmmd, mp->m_postsize,
caStatus status = this->out.copyInHeader ( mp->m_cmmd, mp->m_postsize,
mp->m_dataType, mp->m_count, mp->m_cid, mp->m_available,
& pPayloadOut );
if ( ! status ) {

View File

@@ -4,7 +4,7 @@
* 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.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Author Jeffrey O. Hill
@@ -26,39 +26,33 @@
#include "casAsyncIOI.h"
#include "casMonitor.h"
// Use casErrMessage instead of errMessage to show PV name
#define casErrMessage(S, PM) \
errPrintf(S, __FILE__, __LINE__, ", %s, %s", getName(), PM)
casPVI::casPVI ( casPV & intf ) :
pCAS ( NULL ), pPV ( & intf ), nMonAttached ( 0u ),
casPVI::casPVI ( casPV & intf ) :
pCAS ( NULL ), pPV ( & intf ), nMonAttached ( 0u ),
nIOAttached ( 0u ), deletePending ( false ) {}
casPVI::~casPVI ()
{
//
// all channels should have been destroyed
// (otherwise the server tool is yanking the
//
// all channels should have been destroyed
// (otherwise the server tool is yanking the
// PV out from under the server)
//
casVerify ( this->chanList.count() == 0u );
//
casVerify ( this->chanList.count() == 0u );
//
// all outstanding IO should have been deleted
// when we destroyed the channels
//
casVerify ( this->nIOAttached == 0u );
//
// all outstanding IO should have been deleted
// when we destroyed the channels
//
casVerify ( this->nIOAttached == 0u );
if ( this->nIOAttached ) {
errlogPrintf ( "%u IO objects still attached in destructor\n",
this->nIOAttached );
errlogPrintf ( "The number of IO objected attached is %u\n", this->nIOAttached );
}
//
// all monitors should have been deleted
// when we destroyed the channels
//
casVerify ( this->nMonAttached == 0u );
//
// all monitors should have been deleted
// when we destroyed the channels
//
casVerify ( this->nMonAttached == 0u );
{
epicsGuard < epicsMutex > guard ( this->mutex );
@@ -145,26 +139,26 @@ caStatus casPVI::attachToServer ( caServerI & cas )
caStatus casPVI::updateEnumStringTable ( casCtx & ctxIn )
{
epicsGuard < epicsMutex > guard ( this->mutex );
//
// create a gdd with the "enum string table" application type
//
// gddArray(int app, aitEnum prim, int dimen, ...);
gdd * pTmp = new gddScalar ( gddAppType_enums );
if ( pTmp == NULL ) {
casErrMessage ( S_cas_noMemory,
errMessage ( S_cas_noMemory,
"unable to create gdd for read of application type \"enums\" string"
" conversion table for enumerated PV" );
return S_cas_noMemory;
}
caStatus status = convertContainerMemberToAtomic ( *pTmp,
caStatus status = convertContainerMemberToAtomic ( *pTmp,
gddAppType_enums, MAX_ENUM_STATES );
if ( status != S_cas_success ) {
pTmp->unreference ();
casErrMessage ( status,
"unable to config gdd for read of application type \"enums\" string"
" conversion table for enumerated PV" );
errMessage ( status,
"unable to to config gdd for read of application type \"enums\" string"
" conversion table for enumerated PV");
return status;
}
@@ -175,11 +169,12 @@ caStatus casPVI::updateEnumStringTable ( casCtx & ctxIn )
if ( status == S_cas_success ) {
updateEnumStringTableAsyncCompletion ( *pTmp );
}
else if ( status != S_casApp_asyncCompletion &&
else if ( status != S_casApp_asyncCompletion &&
status != S_casApp_postponeAsyncIO ) {
casErrMessage ( status,
"unable to read application type \"enums\" "
" (string conversion table) from enumerated native type PV" );
errPrintf ( status, __FILE__, __LINE__,
"- unable to read application type \"enums\" "
" (string conversion table) from enumerated native type PV \"%s\"",
this->getName() );
}
pTmp->unreference ();
@@ -190,39 +185,40 @@ caStatus casPVI::updateEnumStringTable ( casCtx & ctxIn )
void casPVI::updateEnumStringTableAsyncCompletion ( const gdd & resp )
{
epicsGuard < epicsMutex > guard ( this->mutex );
if ( resp.isContainer() ) {
casErrMessage ( S_cas_badType,
"Invalid \"enums\" string conversion table for"
" enumerated PV (container instead of vector of strings)" );
errMessage ( S_cas_badType,
"application type \"enums\" string conversion table for"
" enumerated PV was a container (expected vector of strings)" );
return;
}
if ( resp.dimension() == 0 ) {
if ( resp.primitiveType() == aitEnumString ) {
aitString *pStr = (aitString *) resp.dataVoid ();
if ( ! this->enumStrTbl.setString ( 0, pStr->string() ) ) {
casErrMessage ( S_cas_noMemory,
errMessage ( S_cas_noMemory,
"no memory to set enumerated PV string cache" );
}
}
else if ( resp.primitiveType() == aitEnumFixedString ) {
aitFixedString *pStr = (aitFixedString *) resp.dataVoid ();
if ( ! this->enumStrTbl.setString ( 0, pStr->fixed_string ) ) {
casErrMessage ( S_cas_noMemory,
errMessage ( S_cas_noMemory,
"no memory to set enumerated PV string cache" );
}
}
else {
casErrMessage ( S_cas_badType,
errPrintf ( S_cas_badType, __FILE__, __LINE__,
"application type \"enums\" string conversion"
" table for enumerated PV isnt a string type?" );
" table for enumerated PV \"%s\" isnt a string type?",
getName() );
}
}
else if ( resp.dimension() == 1 ) {
gddStatus gdd_status;
aitIndex index, first, count;
gdd_status = resp.getBound ( 0, first, count );
assert ( gdd_status == 0 );
@@ -236,7 +232,7 @@ void casPVI::updateEnumStringTableAsyncCompletion ( const gdd & resp )
aitString *pStr = (aitString *) resp.dataVoid ();
for ( index = 0; index<count; index++ ) {
if ( ! this->enumStrTbl.setString ( index, pStr[index].string() ) ) {
casErrMessage ( S_cas_noMemory,
errMessage ( S_cas_noMemory,
"no memory to set enumerated PV string cache" );
}
}
@@ -245,18 +241,19 @@ void casPVI::updateEnumStringTableAsyncCompletion ( const gdd & resp )
aitFixedString *pStr = (aitFixedString *) resp.dataVoid ();
for ( index = 0; index < count; index++ ) {
if ( ! this->enumStrTbl.setString ( index, pStr[index].fixed_string ) ) {
casErrMessage ( S_cas_noMemory,
errMessage ( S_cas_noMemory,
"no memory to set enumerated PV string cache" );
}
}
}
else {
casErrMessage( S_cas_badType,
"bad \"enums\" string conversion table for enumerated PV" );
errMessage ( S_cas_badType,
"application type \"enums\" string conversion"
" table for enumerated PV isnt a string type?" );
}
}
else {
casErrMessage ( S_cas_badType,
errMessage ( S_cas_badType,
"application type \"enums\" string conversion table"
" for enumerated PV was multi-dimensional"
" (expected vector of strings)" );
@@ -290,7 +287,7 @@ void casPVI::postEvent ( const casEventMask & select, const gdd & event )
}
}
caStatus casPVI::installMonitor (
caStatus casPVI::installMonitor (
casMonitor & mon, tsDLList < casMonitor > & monitorList )
{
epicsGuard < epicsMutex > guard ( this->mutex );
@@ -306,14 +303,14 @@ caStatus casPVI::installMonitor (
}
}
casMonitor * casPVI::removeMonitor (
casMonitor * casPVI::removeMonitor (
tsDLList < casMonitor > & list, ca_uint32_t clientIdIn )
{
epicsGuard < epicsMutex > guard ( this->mutex );
casMonitor * pMon = 0;
//
// (it is reasonable to do a linear search here because
// sane clients will require only one or two monitors
// sane clients will require only one or two monitors
// per channel)
//
tsDLIter < casMonitor > iter = list.firstIter ();
@@ -362,9 +359,9 @@ void casPVI::installChannel ( chanIntfForPV & chan )
epicsGuard < epicsMutex > guard ( this->mutex );
this->chanList.add ( chan );
}
void casPVI::removeChannel (
chanIntfForPV & chan, tsDLList < casMonitor > & src,
void casPVI::removeChannel (
chanIntfForPV & chan, tsDLList < casMonitor > & src,
tsDLList < casMonitor > & dest )
{
epicsGuard < epicsMutex > guard ( this->mutex );
@@ -383,8 +380,8 @@ void casPVI::clearOutstandingReads ( tsDLList < casAsyncIOI > & ioList )
{
epicsGuard < epicsMutex > guard ( this->mutex );
// cancel any pending asynchronous IO
tsDLIter < casAsyncIOI > iterIO =
// cancel any pending asynchronous IO
tsDLIter < casAsyncIOI > iterIO =
ioList.firstIter ();
while ( iterIO.valid () ) {
tsDLIter < casAsyncIOI > tmp = iterIO;
@@ -410,7 +407,7 @@ void casPVI::destroyAllIO ( tsDLList < casAsyncIOI > & ioList )
}
}
void casPVI::installIO (
void casPVI::installIO (
tsDLList < casAsyncIOI > & ioList, casAsyncIOI & io )
{
epicsGuard < epicsMutex > guard ( this->mutex );
@@ -419,7 +416,7 @@ void casPVI::installIO (
this->nIOAttached++;
}
void casPVI::uninstallIO (
void casPVI::uninstallIO (
tsDLList < casAsyncIOI > & ioList, casAsyncIOI & io )
{
{
@@ -520,8 +517,8 @@ aitEnum casPVI::bestExternalType () const
}
}
// CA only does 1D arrays for now
aitIndex casPVI::nativeCount ()
// CA only does 1D arrays for now
aitIndex casPVI::nativeCount ()
{
epicsGuard < epicsMutex > guard ( this->mutex );
if ( this->pPV ) {
@@ -545,3 +542,4 @@ const char * casPVI::getName () const
return "<disconnected>";
}
}

View File

@@ -205,7 +205,7 @@ caStatus casStrmClient :: processMsg ()
if ( bytesLeft < msgSize ) {
status = S_cas_success;
if ( msgSize > this->in.bufferSize() ) {
this->in.expandBuffer ();
this->in.expandBuffer (msgSize);
// msg to large - set up message drain
if ( msgSize > this->in.bufferSize() ) {
caServerI::dumpMsg ( this->pHostName, this->pUserName, & msgTmp, 0,
@@ -338,6 +338,16 @@ caStatus casStrmClient::versionAction ( epicsGuard < casClientMutex > & )
return S_cas_badProtocol;
}
if (!CA_VSUPPORTED(mp->m_count)) {
if ( this->getCAS().getDebugLevel() > 3u ) {
char pHostName[64u];
this->hostName ( pHostName, sizeof ( pHostName ) );
printf ( "\"%s\" is too old\n",
pHostName );
}
return S_cas_badProtocol;
}
double tmp = mp->m_dataType - CA_PROTO_PRIORITY_MIN;
tmp *= epicsThreadPriorityCAServerHigh - epicsThreadPriorityCAServerLow;
tmp /= CA_PROTO_PRIORITY_MAX - CA_PROTO_PRIORITY_MIN;
@@ -1267,6 +1277,14 @@ caStatus casStrmClient :: searchResponse (
const pvExistReturn & retVal )
{
if ( retVal.getStatus() != pverExistsHere ) {
if (msg.m_dataType == DOREPLY ) {
long status = this->out.copyInHeader ( CA_PROTO_NOT_FOUND, 0,
msg.m_dataType, msg.m_count, msg.m_cid, msg.m_available, 0 );
if ( status == S_cas_success ) {
this->out.commitMsg ();
}
}
return S_cas_success;
}
@@ -1362,6 +1380,16 @@ caStatus casStrmClient :: searchAction ( epicsGuard < casClientMutex > & guard )
const char *pChanName = static_cast <char * > ( this->ctx.getData() );
caStatus status;
if (!CA_VSUPPORTED(mp->m_count)) {
if ( this->getCAS().getDebugLevel() > 3u ) {
char pHostName[64u];
this->hostName ( pHostName, sizeof ( pHostName ) );
printf ( "\"%s\" is searching for \"%s\" but is too old\n",
pHostName, pChanName );
}
return S_cas_badProtocol;
}
//
// check the sanity of the message
//
@@ -1431,11 +1459,8 @@ caStatus casStrmClient :: searchAction ( epicsGuard < casClientMutex > & guard )
//
switch ( pver.getStatus() ) {
case pverExistsHere:
status = this->searchResponse ( guard, *mp, pver );
break;
case pverDoesNotExistHere:
status = S_cas_success;
status = this->searchResponse ( guard, *mp, pver );
break;
case pverAsyncCompletion:

View File

@@ -13,42 +13,54 @@
* 505 665 1831
*/
#include <new>
#include <stdlib.h>
#include "epicsAssert.h"
#include "freeList.h"
#define epicsExportSharedSymbols
#include "clientBufMemoryManager.h"
#include "caProto.h"
bufSizeT clientBufMemoryManager::maxSize () const
clientBufMemoryManager::clientBufMemoryManager()
:smallBufFreeList ( 0 )
{
return bufferFactory.largeBufferSize ();
freeListInitPvt ( & this->smallBufFreeList, MAX_MSG_SIZE, 8 );
}
clientBufMemoryManager::~clientBufMemoryManager()
{
freeListCleanup ( this->smallBufFreeList );
}
casBufferParm clientBufMemoryManager::allocate ( bufSizeT newMinSize )
{
casBufferParm parm;
if ( newMinSize <= bufferFactory.smallBufferSize () ) {
parm.pBuf = bufferFactory.newSmallBuffer ();
parm.bufSize = bufferFactory.smallBufferSize ();
}
else if ( newMinSize <= bufferFactory.largeBufferSize () ) {
parm.pBuf = bufferFactory.newLargeBuffer ();
parm.bufSize = bufferFactory.largeBufferSize ();
if ( newMinSize <= MAX_MSG_SIZE ) {
parm.pBuf = (char*)freeListMalloc(this->smallBufFreeList);
parm.bufSize = MAX_MSG_SIZE;
}
else {
parm.pBuf = static_cast < char * > ( ::operator new ( newMinSize ) );
// round size up to multiple of 4K
newMinSize = ((newMinSize-1)|0xfff)+1;
parm.pBuf = (char*)malloc(newMinSize);
parm.bufSize = newMinSize;
}
if(!parm.pBuf)
throw std::bad_alloc();
return parm;
}
void clientBufMemoryManager::release ( char * pBuf, bufSizeT bufSize )
{
if ( bufSize == bufferFactory.smallBufferSize () ) {
bufferFactory.destroySmallBuffer ( pBuf );
}
else if ( bufSize == bufferFactory.largeBufferSize () ) {
bufferFactory.destroyLargeBuffer ( pBuf );
assert(pBuf);
if (bufSize <= MAX_MSG_SIZE) {
freeListFree(this->smallBufFreeList, pBuf);
}
else {
::operator delete ( pBuf );
free(pBuf);
}
}

View File

@@ -16,22 +16,6 @@
typedef unsigned bufSizeT;
static const unsigned bufSizeT_MAX = UINT_MAX;
class casBufferFactory {
public:
casBufferFactory ();
~casBufferFactory ();
unsigned smallBufferSize () const;
char * newSmallBuffer ();
void destroySmallBuffer ( char * pBuf );
unsigned largeBufferSize () const;
char * newLargeBuffer ();
void destroyLargeBuffer ( char * pBuf );
private:
void * smallBufFreeList;
void * largeBufFreeList;
unsigned largeBufferSizePriv;
};
struct casBufferParm {
char * pBuf;
bufSizeT bufSize;
@@ -39,11 +23,15 @@ struct casBufferParm {
class clientBufMemoryManager {
public:
clientBufMemoryManager();
~clientBufMemoryManager();
//! @throws std::bad_alloc on failure
casBufferParm allocate ( bufSizeT newMinSize );
void release ( char * pBuf, bufSizeT bufSize );
bufSizeT maxSize () const;
private:
casBufferFactory bufferFactory;
void * smallBufFreeList;
};
#endif // clientBufMemoryManagerh

View File

@@ -13,6 +13,9 @@
* 505 665 1831
*/
#include <stdexcept>
#include <new>
#include <stdio.h>
#include <string.h>
@@ -155,11 +158,17 @@ bufSizeT inBuf::popCtx ( const inBufCtx &ctx )
}
}
void inBuf::expandBuffer ()
void inBuf::expandBuffer (bufSizeT needed)
{
bufSizeT max = this->memMgr.maxSize();
if ( this->bufSize < max ) {
casBufferParm bufParm = this->memMgr.allocate ( max );
if (needed > bufSize) {
casBufferParm bufParm;
try {
bufParm = this->memMgr.allocate ( needed );
} catch (std::bad_alloc& e) {
// caller must check that buffer size has expended
return;
}
bufSizeT unprocessedBytes = this->bytesPresent ();
memcpy ( bufParm.pBuf, &this->pBuf[this->nextReadIndex], unprocessedBytes );
this->bytesInBuffer = unprocessedBytes;
@@ -170,7 +179,7 @@ void inBuf::expandBuffer ()
}
}
unsigned inBuf::bufferSize () const
bufSizeT inBuf::bufferSize() const
{
return this->bufSize;
}

View File

@@ -82,8 +82,8 @@ public:
//
const inBufCtx pushCtx ( bufSizeT headerSize, bufSizeT bodySize );
bufSizeT popCtx ( const inBufCtx & ); // returns actual size
unsigned bufferSize () const;
void expandBuffer ();
bufSizeT bufferSize () const;
void expandBuffer (bufSizeT needed);
private:
class inBufClient & client;
class clientBufMemoryManager & memMgr;

View File

@@ -59,7 +59,7 @@ caStatus outBuf::allocRawMsg ( bufSizeT msgsize, void **ppMsg )
msgsize = CA_MESSAGE_ALIGN ( msgsize );
if ( msgsize > this->bufSize ) {
this->expandBuffer ();
this->expandBuffer (msgsize);
if ( msgsize > this->bufSize ) {
return S_cas_hugeRequest;
}
@@ -316,11 +316,17 @@ void outBuf::show (unsigned level) const
}
}
void outBuf::expandBuffer ()
void outBuf::expandBuffer (bufSizeT needed)
{
bufSizeT max = this->memMgr.maxSize();
if ( this->bufSize < max ) {
casBufferParm bufParm = this->memMgr.allocate ( max );
if (needed > bufSize) {
casBufferParm bufParm;
try {
bufParm = this->memMgr.allocate ( needed );
} catch (std::bad_alloc& e) {
// caller must check that buffer size has expended
return;
}
memcpy ( bufParm.pBuf, this->pBuf, this->stack );
this->memMgr.release ( this->pBuf, this->bufSize );
this->pBuf = bufParm.pBuf;

View File

@@ -122,7 +122,7 @@ private:
bufSizeT stack;
unsigned ctxRecursCount;
void expandBuffer ();
void expandBuffer (bufSizeT needed);
outBuf ( const outBuf & );
outBuf & operator = ( const outBuf & );

View File

@@ -1,29 +0,0 @@
/*************************************************************************\
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#define epicsExportSharedSymbols
#include "ipIgnoreEntry.h"
#include "casChannelI.h"
#ifdef _MSC_VER
# pragma warning ( push )
# pragma warning ( disable:4660 )
#endif
template class resTable < ipIgnoreEntry, ipIgnoreEntry >;
template class resTable < casChannelI, chronIntId >;
template class resTable < casEventMaskEntry, stringId >;
template class chronIntIdResTable < casChannelI >;
template class tsFreeList < casMonEvent, 1024, epicsMutexNOOP >;
template class tsFreeList < casMonitor, 1024, epicsMutex >;
#ifdef _MSC_VER
# pragma warning ( pop )
#endif

View File

@@ -23,5 +23,4 @@ dbCore_SRCS += asIocRegister.c
PROD_HOST += ascheck
ascheck_SRCS = ascheck.c
ascheck_LIBS = dbCore ca Com
ascheck_LIBS = dbCore ca

View File

@@ -14,14 +14,18 @@ SRC_DIRS += $(IOCDIR)/db
INC += callback.h
INC += dbAccess.h
INC += dbAccessDefs.h
INC += dbCa.h
INC += dbAddr.h
INC += dbBkpt.h
INC += dbCa.h
INC += dbChannel.h
INC += dbConstLink.h
INC += dbConvert.h
INC += dbConvertFast.h
INC += dbConvertJSON.h
INC += dbDbLink.h
INC += dbExtractArray.h
INC += dbEvent.h
INC += dbJLink.h
INC += dbLink.h
INC += dbLock.h
INC += dbNotify.h
@@ -64,9 +68,13 @@ dbCore_SRCS += dbLock.c
dbCore_SRCS += dbAccess.c
dbCore_SRCS += dbBkpt.c
dbCore_SRCS += dbChannel.c
dbCore_SRCS += dbConstLink.c
dbCore_SRCS += dbConvert.c
dbCore_SRCS += dbConvertJSON.c
dbCore_SRCS += dbDbLink.c
dbCore_SRCS += dbFastLinkConv.c
dbCore_SRCS += dbExtractArray.c
dbCore_SRCS += dbJLink.c
dbCore_SRCS += dbLink.c
dbCore_SRCS += dbNotify.c
dbCore_SRCS += dbScan.c
@@ -85,7 +93,6 @@ dbCore_SRCS += dbChannelIO.cpp
dbCore_SRCS += dbSubscriptionIO.cpp
dbCore_SRCS += dbPutNotifyBlocker.cpp
dbCore_SRCS += dbContextReadNotifyCache.cpp
dbCore_SRCS += templateInstances.cpp
dbCore_SRCS += dbIocRegister.c
dbCore_SRCS += chfPlugin.c
dbCore_SRCS += dbState.c

View File

@@ -24,7 +24,6 @@
#include "dbDefs.h"
#include "epicsAtomic.h"
#include "epicsEvent.h"
#include "epicsExit.h"
#include "epicsInterrupt.h"
#include "epicsRingPointer.h"
#include "epicsString.h"
@@ -46,7 +45,6 @@
#include "epicsExport.h"
#include "link.h"
#include "recSup.h"
#include "dbUnitTest.h" /* for testSyncCallback() */
static int callbackQueueSize = 2000;
@@ -82,10 +80,6 @@ static int callbackIsInit;
static char *threadNamePrefix[NUM_CALLBACK_PRIORITIES] = {
"cbLow", "cbMedium", "cbHigh"
};
#define FULL_MSG(name) "callbackRequest: " name " ring buffer full\n"
static char *fullMessage[NUM_CALLBACK_PRIORITIES] = {
FULL_MSG("cbLow"), FULL_MSG("cbMedium"), FULL_MSG("cbHigh")
};
static unsigned int threadPriority[NUM_CALLBACK_PRIORITIES] = {
epicsThreadPriorityScanLow - 1,
epicsThreadPriorityScanLow + 4,
@@ -97,7 +91,7 @@ static int priorityValue[NUM_CALLBACK_PRIORITIES] = {0, 1, 2};
int callbackSetQueueSize(int size)
{
if (callbackIsInit) {
errlogPrintf("Callback system already initialized\n");
fprintf(stderr, "Callback system already initialized\n");
return -1;
}
callbackQueueSize = size;
@@ -107,7 +101,7 @@ int callbackSetQueueSize(int size)
int callbackParallelThreads(int count, const char *prio)
{
if (callbackIsInit) {
errlogPrintf("Callback system already initialized\n");
fprintf(stderr, "Callback system already initialized\n");
return -1;
}
@@ -117,7 +111,7 @@ int callbackParallelThreads(int count, const char *prio)
count = callbackParallelThreadsDefault;
if (count < 1) count = 1;
if (!prio || strcmp(prio, "") == 0 || strcmp(prio, "*") == 0) {
if (!prio || *prio == 0 || strcmp(prio, "*") == 0) {
int i;
for (i = 0; i < NUM_CALLBACK_PRIORITIES; i++) {
@@ -126,30 +120,30 @@ int callbackParallelThreads(int count, const char *prio)
}
else {
dbMenu *pdbMenu;
int i;
if (!pdbbase) {
errlogPrintf("callbackParallelThreads: pdbbase not set\n");
fprintf(stderr, "callbackParallelThreads: pdbbase not set\n");
return -1;
}
/* Find prio in menuPriority */
pdbMenu = dbFindMenu(pdbbase, "menuPriority");
if (pdbMenu) {
int i, gotMatch = 0;
for (i = 0; i < pdbMenu->nChoice; i++) {
gotMatch = (epicsStrCaseCmp(prio, pdbMenu->papChoiceValue[i])==0) ? TRUE : FALSE;
if (gotMatch)
break;
}
if (gotMatch) {
callbackQueue[i].threadsConfigured = count;
return 0;
}
else {
errlogPrintf("Unknown priority \"%s\"\n", prio);
return -1;
}
if (!pdbMenu) {
fprintf(stderr, "callbackParallelThreads: No Priority menu\n");
return -1;
}
for (i = 0; i < pdbMenu->nChoice; i++) {
if (epicsStrCaseCmp(prio, pdbMenu->papChoiceValue[i]) == 0)
goto found;
}
fprintf(stderr, "callbackParallelThreads: "
"Unknown priority \"%s\"\n", prio);
return -1;
found:
callbackQueue[i].threadsConfigured = count;
}
return 0;
}
@@ -289,7 +283,11 @@ int callbackRequest(CALLBACK *pcallback)
pushOK = epicsRingPointerPush(mySet->queue, pcallback);
if (!pushOK) {
epicsInterruptContextMessage(fullMessage[priority]);
char msg[48] = "callbackRequest: ";
strcat(msg, threadNamePrefix[priority]);
strcat(msg, " ring buffer full\n");
epicsInterruptContextMessage(msg);
mySet->queueOverflow = TRUE;
return S_db_bufFull;
}
@@ -354,86 +352,3 @@ void callbackRequestProcessCallbackDelayed(CALLBACK *pcallback,
callbackSetProcess(pcallback, Priority, pRec);
callbackRequestDelayed(pcallback, seconds);
}
/* Sync. process of testSyncCallback()
*
* 1. For each priority, make a call to callbackRequest() for each worker.
* 2. Wait until all callbacks are concurrently being executed
* 3. Last worker to begin executing signals success and begins waking up other workers
* 4. Last worker to wake signals testSyncCallback() to complete
*/
typedef struct {
epicsEventId wait_phase2, wait_phase4;
int nphase2, nphase3;
epicsCallback cb;
} sync_helper;
static void sync_callback(epicsCallback *cb)
{
sync_helper *helper;
callbackGetUser(helper, cb);
testGlobalLock();
assert(helper->nphase2 > 0);
if(--helper->nphase2!=0) {
/* we are _not_ the last to start. */
testGlobalUnlock();
epicsEventMustWait(helper->wait_phase2);
testGlobalLock();
}
/* we are either the last to start, or have been
* woken by the same and must pass the wakeup along
*/
epicsEventMustTrigger(helper->wait_phase2);
assert(helper->nphase2 == 0);
assert(helper->nphase3 > 0);
if(--helper->nphase3==0) {
/* we are the last to wake up. wake up testSyncCallback() */
epicsEventMustTrigger(helper->wait_phase4);
}
testGlobalUnlock();
}
void testSyncCallback(void)
{
sync_helper helper[NUM_CALLBACK_PRIORITIES];
unsigned i;
testDiag("Begin testSyncCallback()");
for(i=0; i<NUM_CALLBACK_PRIORITIES; i++) {
helper[i].wait_phase2 = epicsEventMustCreate(epicsEventEmpty);
helper[i].wait_phase4 = epicsEventMustCreate(epicsEventEmpty);
/* no real need to lock here, but do so anyway so that valgrind can establish
* the locking requirements for sync_helper.
*/
testGlobalLock();
helper[i].nphase2 = helper[i].nphase3 = callbackQueue[i].threadsRunning;
testGlobalUnlock();
callbackSetUser(&helper[i], &helper[i].cb);
callbackSetPriority(i, &helper[i].cb);
callbackSetCallback(sync_callback, &helper[i].cb);
callbackRequest(&helper[i].cb);
}
for(i=0; i<NUM_CALLBACK_PRIORITIES; i++) {
epicsEventMustWait(helper[i].wait_phase4);
}
for(i=0; i<NUM_CALLBACK_PRIORITIES; i++) {
testGlobalLock();
epicsEventDestroy(helper[i].wait_phase2);
epicsEventDestroy(helper[i].wait_phase4);
testGlobalUnlock();
}
testDiag("Complete testSyncCallback()");
}

View File

@@ -42,20 +42,20 @@ typedef struct callbackPvt {
int priority;
void *user; /*for use by callback user*/
void *timer; /*for use by callback itself*/
}epicsCallback;
typedef epicsCallback CALLBACK;
}CALLBACK;
typedef void (*CALLBACKFUNC)(struct callbackPvt*);
#define callbackSetCallback(PFUN,PCALLBACK)\
( (PCALLBACK)->callback = (PFUN) )
#define callbackSetPriority(PRIORITY,PCALLBACK)\
( (PCALLBACK)->priority = (PRIORITY) )
#define callbackSetUser(USER,PCALLBACK)\
( (PCALLBACK)->user = (void *)(USER) )
#define callbackGetUser(USER,PCALLBACK)\
( (USER) = (void *)((CALLBACK *)(PCALLBACK))->user )
#define callbackSetCallback(PFUN, PCALLBACK) \
( (PCALLBACK)->callback = (PFUN) )
#define callbackSetPriority(PRIORITY, PCALLBACK) \
( (PCALLBACK)->priority = (PRIORITY) )
#define callbackGetPriority(PRIORITY, PCALLBACK) \
( (PRIORITY) = (PCALLBACK)->priority )
#define callbackSetUser(USER, PCALLBACK) \
( (PCALLBACK)->user = (void *) (USER) )
#define callbackGetUser(USER, PCALLBACK) \
( (USER) = (PCALLBACK)->user )
epicsShareFunc void callbackInit(void);
epicsShareFunc void callbackStop(void);

View File

@@ -41,8 +41,7 @@
#include "dbAddr.h"
#include "dbBase.h"
#include "dbBkpt.h"
#include "dbCa.h"
#include "dbCommon.h"
#include "dbCommonPvt.h"
#include "dbConvertFast.h"
#include "dbConvert.h"
#include "dbEvent.h"
@@ -50,11 +49,12 @@
#include "dbFldTypes.h"
#include "dbFldTypes.h"
#include "dbLink.h"
#include "dbLock.h"
#include "dbLockPvt.h"
#include "dbNotify.h"
#include "dbScan.h"
#include "dbServer.h"
#include "dbStaticLib.h"
#include "dbStaticPvt.h"
#include "devSup.h"
#include "epicsEvent.h"
#include "link.h"
@@ -77,6 +77,8 @@ static short mapDBFToDBR[DBF_NTYPES] = {
/* DBF_USHORT => */ DBR_USHORT,
/* DBF_LONG => */ DBR_LONG,
/* DBF_ULONG => */ DBR_ULONG,
/* DBF_INT64 => */ DBR_INT64,
/* DBF_UINT64 => */ DBR_UINT64,
/* DBF_FLOAT => */ DBR_FLOAT,
/* DBF_DOUBLE => */ DBR_DOUBLE,
/* DBF_ENUM, => */ DBR_ENUM,
@@ -107,7 +109,7 @@ void dbSpcAsRegisterCallback(SPC_ASCALLBACK func)
long dbPutSpecial(DBADDR *paddr,int pass)
{
long int (*pspecial)()=NULL;
struct rset *prset;
rset *prset;
dbCommon *precord = paddr->precord;
long status=0;
long special=paddr->special;
@@ -139,7 +141,7 @@ long dbPutSpecial(DBADDR *paddr,int pass)
}
static void get_enum_strs(DBADDR *paddr, char **ppbuffer,
struct rset *prset,long *options)
rset *prset,long *options)
{
short field_type=paddr->field_type;
dbFldDes *pdbFldDes = paddr->pfldDes;
@@ -199,7 +201,7 @@ choice_common:
}
static void get_graphics(DBADDR *paddr, char **ppbuffer,
struct rset *prset,long *options)
rset *prset,long *options)
{
struct dbr_grDouble grd;
int got_data=FALSE;
@@ -239,7 +241,7 @@ static void get_graphics(DBADDR *paddr, char **ppbuffer,
}
static void get_control(DBADDR *paddr, char **ppbuffer,
struct rset *prset,long *options)
rset *prset,long *options)
{
struct dbr_ctrlDouble ctrld;
int got_data=FALSE;
@@ -279,7 +281,7 @@ static void get_control(DBADDR *paddr, char **ppbuffer,
}
static void get_alarm(DBADDR *paddr, char **ppbuffer,
struct rset *prset, long *options)
rset *prset, long *options)
{
char *pbuffer = *ppbuffer;
struct dbr_alDouble ald = {epicsNAN, epicsNAN, epicsNAN, epicsNAN};
@@ -291,14 +293,10 @@ static void get_alarm(DBADDR *paddr, char **ppbuffer,
if (*options & DBR_AL_LONG) {
struct dbr_alLong *pal = (struct dbr_alLong*) pbuffer;
pal->upper_alarm_limit = finite(ald.upper_alarm_limit) ?
(epicsInt32) ald.upper_alarm_limit : 0;
pal->upper_warning_limit = finite(ald.upper_warning_limit) ?
(epicsInt32) ald.upper_warning_limit : 0;
pal->lower_warning_limit = finite(ald.lower_warning_limit) ?
(epicsInt32) ald.lower_warning_limit : 0;
pal->lower_alarm_limit = finite(ald.lower_alarm_limit) ?
(epicsInt32) ald.lower_alarm_limit : 0;
pal->upper_alarm_limit = (epicsInt32) ald.upper_alarm_limit;
pal->upper_warning_limit = (epicsInt32) ald.upper_warning_limit;
pal->lower_warning_limit = (epicsInt32) ald.lower_warning_limit;
pal->lower_alarm_limit = (epicsInt32) ald.lower_alarm_limit;
if (no_data)
*options ^= DBR_AL_LONG; /*Turn off option*/
@@ -328,7 +326,7 @@ static void getOptions(DBADDR *paddr, char **poriginal, long *options,
void *pflin)
{
db_field_log *pfl= (db_field_log *)pflin;
struct rset *prset;
rset *prset;
short field_type;
dbCommon *pcommon;
char *pbuffer = *poriginal;
@@ -368,7 +366,7 @@ static void getOptions(DBADDR *paddr, char **poriginal, long *options,
memset(pbuffer, '\0', dbr_precision_size);
if((field_type==DBF_FLOAT || field_type==DBF_DOUBLE)
&& prset && prset->get_precision ){
(*prset->get_precision)(paddr,pbuffer);
(*prset->get_precision)(paddr,(long *)pbuffer);
} else {
*options ^= DBR_PRECISION; /*Turn off DBR_PRECISION*/
}
@@ -397,7 +395,7 @@ static void getOptions(DBADDR *paddr, char **poriginal, long *options,
*poriginal = pbuffer;
}
struct rset * dbGetRset(const struct dbAddr *paddr)
rset * dbGetRset(const struct dbAddr *paddr)
{
struct dbFldDes *pfldDes = paddr->pfldDes;
@@ -471,7 +469,7 @@ long dbScanPassive(dbCommon *pfrom, dbCommon *pto)
*/
long dbProcess(dbCommon *precord)
{
struct rset *prset = precord->rset;
rset *prset = precord->rset;
dbRecordType *pdbRecordType = precord->rdes;
unsigned char tpro = precord->tpro;
char context[40] = "";
@@ -650,7 +648,7 @@ long dbNameToAddr(const char *pname, DBADDR *paddr)
paddr->dbr_field_type = mapDBFToDBR[dbfType];
if (paddr->special == SPC_DBADDR) {
struct rset *prset = dbGetRset(paddr);
rset *prset = dbGetRset(paddr);
/* Let record type modify paddr */
if (prset && prset->cvt_dbaddr) {
@@ -671,7 +669,7 @@ long dbNameToAddr(const char *pname, DBADDR *paddr)
paddr->dbr_field_type = DBR_CHAR;
} else if (dbfType >= DBF_INLINK && dbfType <= DBF_FWDLINK) {
/* Clients see a char array, but keep original dbfType */
paddr->no_elements = PVNAME_STRINGSZ + 12;
paddr->no_elements = PVLINK_STRINGSZ;
paddr->field_size = 1;
paddr->dbr_field_type = DBR_CHAR;
} else {
@@ -685,6 +683,32 @@ finish:
return status;
}
void dbInitEntryFromAddr(struct dbAddr *paddr, DBENTRY *pdbentry)
{
struct dbCommon *prec = paddr->precord;
dbCommonPvt *ppvt = CONTAINER(prec, dbCommonPvt, common);
memset((char *)pdbentry,'\0',sizeof(DBENTRY));
pdbentry->pdbbase = pdbbase;
pdbentry->precordType = prec->rdes;
pdbentry->precnode = ppvt->recnode;
pdbentry->pflddes = paddr->pfldDes;
pdbentry->pfield = paddr->pfield;
pdbentry->indfield = paddr->pfldDes->indRecordType;
}
void dbInitEntryFromRecord(struct dbCommon *prec, DBENTRY *pdbentry)
{
dbCommonPvt *ppvt = CONTAINER(prec, dbCommonPvt, common);
memset((char *)pdbentry,'\0',sizeof(DBENTRY));
pdbentry->pdbbase = pdbbase;
pdbentry->precordType = prec->rdes;
pdbentry->precnode = ppvt->recnode;
}
long dbValueSize(short dbr_type)
{
/* sizes for value associated with each DBR request type */
@@ -696,6 +720,8 @@ long dbValueSize(short dbr_type)
sizeof(epicsUInt16), /* USHORT */
sizeof(epicsInt32), /* LONG */
sizeof(epicsUInt32), /* ULONG */
sizeof(epicsInt64), /* INT64 */
sizeof(epicsUInt64), /* UINT64 */
sizeof(epicsFloat32), /* FLOAT */
sizeof(epicsFloat64), /* DOUBLE */
sizeof(epicsEnum16)}; /* ENUM */
@@ -842,7 +868,7 @@ long dbGet(DBADDR *paddr, short dbrType,
db_field_log *pfl = (db_field_log *)pflin;
short field_type;
long capacity, no_elements, offset;
struct rset *prset;
rset *prset;
long status = 0;
if (options && *options)
@@ -977,19 +1003,25 @@ devSup* dbDSETtoDevSup(dbRecordType *prdes, struct dset *pdset) {
static long dbPutFieldLink(DBADDR *paddr,
short dbrType, const void *pbuffer, long nRequest)
{
dbLinkInfo link_info;
DBADDR *pdbaddr = NULL;
dbCommon *precord = paddr->precord;
dbCommon *lockrecs[2];
dbLocker locker;
dbFldDes *pfldDes = paddr->pfldDes;
long special = paddr->special;
struct link *plink = (struct link *)paddr->pfield;
const char *pstring = (const char *)pbuffer;
DBENTRY dbEntry;
struct dsxt *old_dsxt = NULL;
struct dset *new_dset = NULL;
struct dsxt *new_dsxt = NULL;
devSup *new_devsup = NULL;
long status;
int isDevLink;
short scan;
STATIC_ASSERT(DBLOCKER_NALLOC>=2);
switch (dbrType) {
case DBR_CHAR:
case DBR_UCHAR:
@@ -1004,31 +1036,57 @@ static long dbPutFieldLink(DBADDR *paddr,
return S_db_badDbrtype;
}
dbInitEntry(pdbbase, &dbEntry);
status = dbFindRecord(&dbEntry, precord->name);
if (!status) status = dbFindField(&dbEntry, pfldDes->name);
if (status) goto finish;
status = dbParseLink(pstring, pfldDes->field_type, &link_info, 0);
if (status)
return status;
if (link_info.ltype == PV_LINK &&
(link_info.modifiers & (pvlOptCA | pvlOptCP | pvlOptCPP)) == 0) {
DBADDR tempaddr;
if (dbNameToAddr(link_info.target, &tempaddr)==0) {
/* This will become a DB link. */
pdbaddr = malloc(sizeof(*pdbaddr));
if (!pdbaddr) {
status = S_db_noMemory;
goto cleanup;
}
*pdbaddr = tempaddr; /* struct copy */
}
}
isDevLink = ellCount(&precord->rdes->devList) > 0 &&
(strcmp(pfldDes->name, "INP") == 0 ||
strcmp(pfldDes->name, "OUT") == 0);
pfldDes->isDevLink;
dbLockSetGblLock();
dbLockSetRecordLock(precord);
memset(&locker, 0, sizeof(locker));
lockrecs[0] = precord;
lockrecs[1] = pdbaddr ? pdbaddr->precord : NULL;
dbLockerPrepare(&locker, lockrecs, 2);
dbScanLockMany(&locker);
scan = precord->scan;
if (isDevLink) {
devSup *pdevSup = dbDTYPtoDevSup(precord->rdes, precord->dtyp);
if (pdevSup) {
new_dset = pdevSup->pdset;
new_dsxt = pdevSup->pdsxt;
new_devsup = dbDTYPtoDevSup(precord->rdes, precord->dtyp);
if (new_devsup) {
new_dset = new_devsup->pdset;
new_dsxt = new_devsup->pdsxt;
}
}
if (dbCanSetLink(plink, &link_info, new_devsup)) {
/* link type mis-match prevents assignment */
status = S_dbLib_badField;
goto unlock;
}
if (isDevLink) {
if (precord->dset) {
pdevSup = dbDSETtoDevSup(precord->rdes, precord->dset);
if (pdevSup)
old_dsxt = pdevSup->pdsxt;
devSup *old_devsup = dbDSETtoDevSup(precord->rdes, precord->dset);
if (old_devsup)
old_dsxt = old_devsup->pdsxt;
}
if (new_dsxt == NULL ||
@@ -1051,30 +1109,17 @@ static long dbPutFieldLink(DBADDR *paddr,
}
}
switch (plink->type) { /* Old link type */
case DB_LINK:
case CA_LINK:
dbRemoveLink(plink);
break;
case PV_LINK:
case CONSTANT:
break; /* do nothing */
case MACRO_LINK:
break; /* should never get here */
default: /* Hardware address */
if (!isDevLink) {
status = S_db_badHWaddr;
goto restoreScan;
}
break;
if (dbLinkIsDefined(plink)) {
dbRemoveLink(&locker, plink); /* Clear out old link */
}
else if (!isDevLink) {
status = S_db_badHWaddr;
goto restoreScan;
}
if (special) status = dbPutSpecial(paddr, 0);
if (!status) status = dbPutString(&dbEntry, pstring);
if (!status) status = dbSetLink(plink, &link_info, new_devsup);
if (!status && special) status = dbPutSpecial(paddr, 1);
@@ -1101,11 +1146,10 @@ static long dbPutFieldLink(DBADDR *paddr,
switch (plink->type) { /* New link type */
case PV_LINK:
dbAddLink(precord, plink, pfldDes->field_type);
break;
case CONSTANT:
break; /* do nothing */
case JSON_LINK:
dbAddLink(&locker, plink, pfldDes->field_type, pdbaddr);
break;
case DB_LINK:
case CA_LINK:
@@ -1131,9 +1175,10 @@ postScanEvent:
if (scan != precord->scan)
db_post_events(precord, &precord->scan, DBE_VALUE | DBE_LOG);
unlock:
dbLockSetGblUnlock();
finish:
dbFinishEntry(&dbEntry);
dbScanUnlockMany(&locker);
dbLockerFinalize(&locker);
cleanup:
free(link_info.target);
return status;
}
@@ -1219,7 +1264,7 @@ long dbPut(DBADDR *paddr, short dbrType,
long no_elements = paddr->no_elements;
long special = paddr->special;
void *pfieldsave = paddr->pfield;
struct rset *prset = dbGetRset(paddr);
rset *prset = dbGetRset(paddr);
long status = 0;
long offset;
dbFldDes *pfldDes;

View File

@@ -20,6 +20,7 @@
#include "epicsTime.h"
#include "dbBase.h"
#include "dbAddr.h"
#include "recSup.h"
#ifdef INCLdb_accessh_epicsExportSharedSymbols
# define epicsExportSharedSymbols
@@ -181,6 +182,7 @@ struct dbr_alDouble {DBRalDouble};
#define S_db_badChoice (M_dbAccess|13) /*Illegal choice*/
#define S_db_badField (M_dbAccess|15) /*Illegal field value*/
#define S_db_lsetLogic (M_dbAccess|17) /*Logic error generating lock sets*/
#define S_db_noLSET (M_dbAccess|21) /*No link support table or entry*/
#define S_db_noRSET (M_dbAccess|31) /*missing record support entry table*/
#define S_db_noSupport (M_dbAccess|33) /*RSET or DSXT routine not defined*/
#define S_db_BadSub (M_dbAccess|35) /*Subroutine not found*/
@@ -202,7 +204,7 @@ struct dbr_alDouble {DBRalDouble};
#define S_db_bufFull (M_dbAccess|68) /*Buffer full*/
epicsShareFunc long dbPutSpecial(struct dbAddr *paddr,int pass);
epicsShareFunc struct rset * dbGetRset(const struct dbAddr *paddr);
epicsShareFunc rset * dbGetRset(const struct dbAddr *paddr);
epicsShareFunc long dbPutAttribute(
const char *recordTypename,const char *name,const char*value);
epicsShareFunc int dbIsValueField(const struct dbFldDes *pdbFldDes);

View File

@@ -410,7 +410,7 @@ long dbd(const char *record_name)
precord = addr.precord;
if (!(precord->bkpt & BKPT_ON_MASK)) {
if (! precord->bkpt & BKPT_ON_MASK) {
printf(" BKPT> No breakpoint set in this record\n");
return(S_db_bkptNotSet);
}

View File

@@ -26,12 +26,13 @@
#include "stdlib.h"
#include <memory> // std::auto_ptr
#include "tsDLList.h"
#include "tsFreeList.h"
#include "resourceLib.h"
#include "cacIO.h"
#include "compilerDependencies.h"
#include "epicsMemory.h"
#ifdef dbCACh_restore_epicsExportSharedSymbols
# define epicsExportSharedSymbols
@@ -193,8 +194,9 @@ private:
epicsMutex & mutex;
epicsMutex & cbMutex;
cacContextNotify & notify;
epics_auto_ptr < cacContext > pNetContext;
std::auto_ptr < cacContext > pNetContext;
char * pStateNotifyCache;
bool isolated;
cacChannel & createChannel (
epicsGuard < epicsMutex > &,

View File

@@ -11,7 +11,7 @@
* Original Authors: Bob Dalesio and Marty Kraimer
* Date: 26MAR96
*/
#define EPICS_DBCA_PRIVATE_API
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
@@ -28,6 +28,7 @@
#include "epicsPrint.h"
#include "epicsString.h"
#include "epicsThread.h"
#include "epicsAtomic.h"
#include "epicsTime.h"
#include "errlog.h"
#include "errMdef.h"
@@ -44,13 +45,18 @@
#include "dbCaPvt.h"
#include "dbCommon.h"
#include "db_convert.h"
#include "dbLink.h"
#include "dbLock.h"
#include "dbScan.h"
#include "link.h"
#include "recGbl.h"
#include "recSup.h"
/* defined in dbContext.cpp
* Setup local CA access
*/
extern void dbServiceIOInit();
extern int dbServiceIsolate;
static ELLLIST workList = ELLLIST_INIT; /* Work list for dbCaTask */
static epicsMutexId workListLock; /*Mutual exclusions semaphores for workList*/
@@ -58,7 +64,7 @@ static epicsEventId workListEvent; /*wakeup event for dbCaTask*/
static int removesOutstanding = 0;
#define removesOutstandingWarning 10000
static volatile enum {
static volatile enum dbCaCtl_t {
ctlInit, ctlRun, ctlPause, ctlExit
} dbCaCtl;
static epicsEventId startStopEvent;
@@ -68,57 +74,47 @@ struct ca_client_context * dbCaClientContext;
/* Forward declarations */
static void dbCaTask(void *);
static lset dbCa_lset;
#define printLinks(pcaLink) \
errlogPrintf("%s has DB CA link to %s\n",\
pcaLink->plink->value.pv_link.precord->name, pcaLink->pvname)
pcaLink->plink->precord->name, pcaLink->pvname)
static int dbca_chan_count;
/* caLink locking
*
* workListLock
* This is only used to put request into and take them out of workList.
* While this is locked no other locks are taken
* Lock ordering:
* dbScanLock -> caLink.lock -> workListLock
*
* dbScanLock
* dbCaAddLink and dbCaRemoveLink are only called by dbAccess or iocInit
* They are only called by dbAccess when it has a global lock on lock set.
* It is assumed that ALL other dbCaxxx calls are made only if dbScanLock
* is already active. These routines are intended for use by record/device
* support.
* workListLock:
* Guards access to workList.
*
* caLink.lock
* Any code that use a caLink takes this lock and releases it when done
* dbScanLock:
* All dbCa* functions operating on a single link may only be called when
* the record containing the DBLINK is locked. Including:
* dbCaGet*()
* isConnected()
* dbCaPutLink()
* scanForward()
* dbCaAddLinkCallback()
* dbCaRemoveLink()
*
* dbCaTask and the channel access callbacks NEVER access anything in the
* records except after locking caLink.lock and checking that caLink.plink
* is not null. They NEVER call dbScanLock.
* Guard the pointer plink.value.pv_link.pvt, but not the struct caLink
* which is pointed to.
*
* The above is necessary to prevent deadlocks and attempts to use a caLink
* that has been deleted.
* caLink.lock:
* Guards the caLink structure (but not the struct DBLINK)
*
* Just a few words about handling dbCaRemoveLink because this is when
* it is essential that nothing tries to use a caLink that has been freed.
* The dbCaTask only locks caLink, and must not lock the record (a violation of lock order).
*
* dbCaRemoveLink is called when links are being modified. This is only
* done with the dbScan mechanism guranteeing that nothing from
* database access trys to access the record containing the caLink.
* During link modification or IOC shutdown the pca->plink pointer (guarded by caLink.lock)
* is used as a flag to indicate that a link is no longer active.
*
* Thus the problem is to make sure that nothing from channel access
* accesses a caLink that is deleted. This is done as follows.
* References to the struct caLink are owned by the dbCaTask, and any scanOnceCallback()
* which is in progress.
*
* dbCaRemoveLink does the following:
* epicsMutexMustLock(pca->lock);
* pca->plink = 0;
* plink->value.pv_link.pvt = 0;
* epicsMutexUnlock(pca->lock);
* addAction(pca,CA_CLEAR_CHANNEL);
*
* dbCaTask issues a ca_clear_channel and then frees the caLink.
*
* If any channel access callback gets called before the ca_clear_channel
* it finds pca->plink==0 and does nothing. Once ca_clear_channel
* is called no other callback for this caLink will be called.
* The libca and scanOnceCallback callbacks take no action if pca->plink==NULL.
*
* dbCaPutLinkCallback causes an additional complication because
* when dbCaRemoveLink is called the callback may not have occured.
@@ -159,11 +155,23 @@ static void addAction(caLink *pca, short link_action)
epicsEventSignal(workListEvent);
}
static void dbCaLinkFree(caLink *pca)
static void caLinkInc(caLink *pca)
{
assert(epicsAtomicGetIntT(&pca->refcount)>0);
epicsAtomicIncrIntT(&pca->refcount);
}
static void caLinkDec(caLink *pca)
{
int cnt;
dbCaCallback callback;
void *userPvt = 0;
cnt = epicsAtomicDecrIntT(&pca->refcount);
assert(cnt>=0);
if(cnt>0)
return;
if (pca->chid) {
ca_clear_channel(pca->chid);
--dbca_chan_count;
@@ -184,52 +192,86 @@ static void dbCaLinkFree(caLink *pca)
if (callback) callback(userPvt);
}
/* Block until worker thread has processed all previously queued actions.
* Does not prevent additional actions from being queued.
*/
void dbCaSync(void)
{
epicsEventId wake;
caLink templink;
/* we only partially initialize templink.
* It has no link field and no subscription
* so the worker must handle it early
*/
memset(&templink, 0, sizeof(templink));
templink.refcount = 1;
wake = epicsEventMustCreate(epicsEventEmpty);
templink.lock = epicsMutexMustCreate();
templink.userPvt = wake;
addAction(&templink, CA_SYNC);
epicsEventMustWait(wake);
/* Worker holds workListLock when calling epicsEventMustTrigger()
* we cycle through workListLock to ensure worker call to
* epicsEventMustTrigger() returns before we destroy the event.
*/
epicsMutexMustLock(workListLock);
epicsMutexUnlock(workListLock);
assert(templink.refcount==1);
epicsMutexDestroy(templink.lock);
epicsEventDestroy(wake);
}
epicsShareFunc unsigned long dbCaGetUpdateCount(struct link *plink)
{
caLink *pca = (caLink *)plink->value.pv_link.pvt;
unsigned long ret;
if (!pca) return (unsigned long)-1;
epicsMutexMustLock(pca->lock);
ret = pca->nUpdate;
epicsMutexUnlock(pca->lock);
return ret;
}
void dbCaCallbackProcess(void *userPvt)
{
struct link *plink = (struct link *)userPvt;
dbCommon *pdbCommon = plink->value.pv_link.precord;
dbScanLock(pdbCommon);
pdbCommon->rset->process(pdbCommon);
dbScanUnlock(pdbCommon);
dbLinkAsyncComplete(plink);
}
void dbCaShutdown(void)
{
if (dbCaCtl == ctlRun || dbCaCtl == ctlPause) {
dbCaCtl = ctlExit;
epicsEventSignal(workListEvent);
epicsEventMustWait(startStopEvent);
epicsEventDestroy(startStopEvent);
} else {
/* manually cleanup queue since dbCa thread isn't running
* which only happens in unit tests
*/
caLink *pca;
epicsMutexMustLock(workListLock);
while((pca=(caLink*)ellGet(&workList))!=NULL) {
if(pca->link_action&CA_CLEAR_CHANNEL) {
dbCaLinkFree(pca);
}
}
epicsMutexUnlock(workListLock);
}
enum dbCaCtl_t cur = dbCaCtl;
assert(cur == ctlRun || cur == ctlPause);
dbCaCtl = ctlExit;
epicsEventSignal(workListEvent);
epicsEventMustWait(startStopEvent);
}
void dbCaLinkInitIsolated(void)
static void dbCaLinkInitImpl(int isolate)
{
dbServiceIsolate = isolate;
dbServiceIOInit();
if (!workListLock)
workListLock = epicsMutexMustCreate();
if (!workListEvent)
workListEvent = epicsEventMustCreate(epicsEventEmpty);
dbCaCtl = ctlExit;
}
void dbCaLinkInit(void)
{
dbServiceIOInit();
dbCaLinkInitIsolated();
startStopEvent = epicsEventMustCreate(epicsEventEmpty);
if(!startStopEvent)
startStopEvent = epicsEventMustCreate(epicsEventEmpty);
dbCaCtl = ctlPause;
epicsThreadCreate("dbCaLink", epicsThreadPriorityMedium,
@@ -238,6 +280,16 @@ void dbCaLinkInit(void)
epicsEventMustWait(startStopEvent);
}
void dbCaLinkInitIsolated(void)
{
dbCaLinkInitImpl(1);
}
void dbCaLinkInit(void)
{
dbCaLinkInitImpl(0);
}
void dbCaRun(void)
{
if (dbCaCtl == ctlPause) {
@@ -262,6 +314,7 @@ void dbCaAddLinkCallback(struct link *plink,
assert(!plink->value.pv_link.pvt);
pca = (caLink *)dbCalloc(1, sizeof(caLink));
pca->refcount = 1;
pca->lock = epicsMutexMustCreate();
pca->plink = plink;
pca->pvname = epicsStrDup(plink->value.pv_link.pvname);
@@ -270,13 +323,20 @@ void dbCaAddLinkCallback(struct link *plink,
pca->userPvt = userPvt;
epicsMutexMustLock(pca->lock);
plink->lset = &dbCa_lset;
plink->type = CA_LINK;
plink->value.pv_link.pvt = pca;
addAction(pca, CA_CONNECT);
epicsMutexUnlock(pca->lock);
}
void dbCaRemoveLink(struct link *plink)
long dbCaAddLink(struct dbLocker *locker, struct link *plink, short dbfType)
{
dbCaAddLinkCallback(plink, 0, 0, NULL);
return 0;
}
void dbCaRemoveLink(struct dbLocker *locker, struct link *plink)
{
caLink *pca = (caLink *)plink->value.pv_link.pvt;
@@ -284,13 +344,16 @@ void dbCaRemoveLink(struct link *plink)
epicsMutexMustLock(pca->lock);
pca->plink = 0;
plink->value.pv_link.pvt = 0;
plink->value.pv_link.pvlMask = 0;
plink->type = PV_LINK;
plink->lset = NULL;
/* Unlock before addAction or dbCaTask might free first */
epicsMutexUnlock(pca->lock);
addAction(pca, CA_CLEAR_CHANNEL);
}
long dbCaGetLink(struct link *plink,short dbrType, void *pdest,
epicsEnum16 *pstat, epicsEnum16 *psevr, long *nelements)
long dbCaGetLink(struct link *plink, short dbrType, void *pdest,
long *nelements)
{
caLink *pca = (caLink *)plink->value.pv_link.pvt;
long status = 0;
@@ -343,15 +406,15 @@ long dbCaGetLink(struct link *plink,short dbrType, void *pdest,
assert(pca->pgetNative);
status = fConvert(pca->pgetNative, pdest, 0);
} else {
long ntoget = *nelements;
unsigned long ntoget = *nelements;
struct dbAddr dbAddr;
long (*aConvert)(struct dbAddr *paddr, void *to, long nreq, long nto, long off);
aConvert = dbGetConvertRoutine[newType][dbrType];
assert(pca->pgetNative);
if (ntoget > pca->nelements)
ntoget = pca->nelements;
if (ntoget > pca->usedelements)
ntoget = pca->usedelements;
*nelements = ntoget;
memset((void *)&dbAddr, 0, sizeof(dbAddr));
@@ -362,13 +425,23 @@ long dbCaGetLink(struct link *plink,short dbrType, void *pdest,
aConvert(&dbAddr, pdest, ntoget, ntoget, 0);
}
done:
if (pstat) *pstat = pca->stat;
if (psevr) *psevr = pca->sevr;
if (link_action) addAction(pca, link_action);
if (link_action)
addAction(pca, link_action);
if (!status)
recGblInheritSevr(plink->value.pv_link.pvlMask & pvlOptMsMode,
plink->precord, pca->stat, pca->sevr);
epicsMutexUnlock(pca->lock);
return status;
}
static long dbCaPutAsync(struct link *plink,short dbrType,
const void *pbuffer,long nRequest)
{
return dbCaPutLinkCallback(plink, dbrType, pbuffer, nRequest,
dbCaCallbackProcess, plink);
}
long dbCaPutLinkCallback(struct link *plink,short dbrType,
const void *pbuffer,long nRequest,dbCaCallback callback,void *userPvt)
{
@@ -406,6 +479,7 @@ long dbCaPutLinkCallback(struct link *plink,short dbrType,
if (!pca->pputNative) {
pca->pputNative = dbCalloc(pca->nelements,
dbr_value_size[ca_field_type(pca->chid)]);
pca->putnelements = 0;
/* Fixed and disabled by ANJ, see comment above.
plink->value.pv_link.pvlMask |= pvlOptOutNative;
*/
@@ -415,6 +489,7 @@ long dbCaPutLinkCallback(struct link *plink,short dbrType,
fConvert = dbFastPutConvertRoutine[dbrType][newType];
status = fConvert(pbuffer, pca->pputNative, 0);
pca->putnelements = 1;
} else {
struct dbAddr dbAddr;
long (*aConvert)(struct dbAddr *paddr, const void *from, long nreq, long nfrom, long off);
@@ -427,10 +502,7 @@ long dbCaPutLinkCallback(struct link *plink,short dbrType,
if(nRequest>pca->nelements)
nRequest = pca->nelements;
status = aConvert(&dbAddr, pbuffer, nRequest, pca->nelements, 0);
if(nRequest<pca->nelements) {
long elemsize = dbr_value_size[ca_field_type(pca->chid)];
memset(nRequest*elemsize+(char*)pca->pputNative, 0, (pca->nelements-nRequest)*elemsize);
}
pca->putnelements = nRequest;
}
link_action |= CA_WRITE_NATIVE;
pca->gotOutNative = TRUE;
@@ -450,7 +522,13 @@ long dbCaPutLinkCallback(struct link *plink,short dbrType,
return status;
}
int dbCaIsLinkConnected(const struct link *plink)
long dbCaPutLink(struct link *plink, short dbrType,
const void *pbuffer, long nRequest)
{
return dbCaPutLinkCallback(plink, dbrType, pbuffer, nRequest, 0, NULL);
}
static int isConnected(const struct link *plink)
{
caLink *pca;
@@ -460,7 +538,7 @@ int dbCaIsLinkConnected(const struct link *plink)
return pca->isConnected;
}
void dbCaScanFwdLink(struct link *plink) {
static void scanForward(struct link *plink) {
short fwdLinkValue = 1;
if (plink->value.pv_link.pvlMask & pvlOptFWD)
@@ -479,7 +557,7 @@ void dbCaScanFwdLink(struct link *plink) {
return -1; \
}
long dbCaGetNelements(const struct link *plink, long *nelements)
static long getElements(const struct link *plink, long *nelements)
{
caLink *pca;
@@ -489,7 +567,7 @@ long dbCaGetNelements(const struct link *plink, long *nelements)
return 0;
}
long dbCaGetAlarm(const struct link *plink,
static long getAlarm(const struct link *plink,
epicsEnum16 *pstat, epicsEnum16 *psevr)
{
caLink *pca;
@@ -501,7 +579,7 @@ long dbCaGetAlarm(const struct link *plink,
return 0;
}
long dbCaGetTimeStamp(const struct link *plink,
static long getTimeStamp(const struct link *plink,
epicsTimeStamp *pstamp)
{
caLink *pca;
@@ -512,7 +590,7 @@ long dbCaGetTimeStamp(const struct link *plink,
return 0;
}
int dbCaGetLinkDBFtype(const struct link *plink)
static int getDBFtype(const struct link *plink)
{
caLink *pca;
int type;
@@ -543,7 +621,7 @@ long dbCaGetAttributes(const struct link *plink,
return 0;
}
long dbCaGetControlLimits(const struct link *plink,
static long getControlLimits(const struct link *plink,
double *low, double *high)
{
caLink *pca;
@@ -559,7 +637,7 @@ long dbCaGetControlLimits(const struct link *plink,
return gotAttributes ? 0 : -1;
}
long dbCaGetGraphicLimits(const struct link *plink,
static long getGraphicLimits(const struct link *plink,
double *low, double *high)
{
caLink *pca;
@@ -575,7 +653,7 @@ long dbCaGetGraphicLimits(const struct link *plink,
return gotAttributes ? 0 : -1;
}
long dbCaGetAlarmLimits(const struct link *plink,
static long getAlarmLimits(const struct link *plink,
double *lolo, double *low, double *high, double *hihi)
{
caLink *pca;
@@ -593,7 +671,7 @@ long dbCaGetAlarmLimits(const struct link *plink,
return gotAttributes ? 0 : -1;
}
long dbCaGetPrecision(const struct link *plink, short *precision)
static long getPrecision(const struct link *plink, short *precision)
{
caLink *pca;
int gotAttributes;
@@ -605,7 +683,7 @@ long dbCaGetPrecision(const struct link *plink, short *precision)
return gotAttributes ? 0 : -1;
}
long dbCaGetUnits(const struct link *plink,
static long getUnits(const struct link *plink,
char *units, int unitsSize)
{
caLink *pca;
@@ -620,6 +698,63 @@ long dbCaGetUnits(const struct link *plink,
return gotAttributes ? 0 : -1;
}
static long doLocked(struct link *plink, dbLinkUserCallback rtn, void *priv)
{
caLink *pca;
long status;
pcaGetCheck
status = rtn(plink, priv);
epicsMutexUnlock(pca->lock);
return status;
}
static void scanComplete(void *raw, dbCommon *prec)
{
caLink *pca = raw;
epicsMutexMustLock(pca->lock);
if(!pca->plink) {
/* IOC shutdown or link re-targeted. Do nothing. */
} else if(pca->scanningOnce==0) {
errlogPrintf("dbCa.c complete callback w/ scanningOnce==0\n");
} else if(--pca->scanningOnce){
/* another scan is queued */
if(scanOnceCallback(prec, scanComplete, raw)) {
errlogPrintf("dbCa.c failed to re-queue scanOnce\n");
} else
caLinkInc(pca);
}
epicsMutexUnlock(pca->lock);
caLinkDec(pca);
}
/* must be called with pca->lock held */
static void scanLinkOnce(dbCommon *prec, caLink *pca) {
if(pca->scanningOnce==0) {
if(scanOnceCallback(prec, scanComplete, pca)) {
errlogPrintf("dbCa.c failed to queue scanOnce\n");
} else
caLinkInc(pca);
}
if(pca->scanningOnce<5)
pca->scanningOnce++;
/* else too many scans queued */
}
static lset dbCa_lset = {
0, 1, /* not Constant, Volatile */
NULL, dbCaRemoveLink,
NULL, NULL, NULL,
isConnected,
getDBFtype, getElements,
dbCaGetLink,
getControlLimits, getGraphicLimits, getAlarmLimits,
getPrecision, getUnits,
getAlarm, getTimeStamp,
dbCaPutLink, dbCaPutAsync,
scanForward, doLocked
};
static void connectionCallback(struct connection_handler_args arg)
{
caLink *pca;
@@ -634,13 +769,13 @@ static void connectionCallback(struct connection_handler_args arg)
pca->isConnected = (ca_state(arg.chid) == cs_conn);
if (!pca->isConnected) {
struct pv_link *ppv_link = &plink->value.pv_link;
dbCommon *precord = ppv_link->precord;
dbCommon *precord = plink->precord;
pca->nDisconnect++;
if (precord &&
((ppv_link->pvlMask & pvlOptCP) ||
((ppv_link->pvlMask & pvlOptCPP) && precord->scan == 0)))
scanOnce(precord);
scanLinkOnce(precord, pca);
goto done;
}
pca->hasReadAccess = ca_read_access(arg.chid);
@@ -649,16 +784,11 @@ static void connectionCallback(struct connection_handler_args arg)
if (pca->gotFirstConnection) {
if (pca->nelements != ca_element_count(arg.chid) ||
pca->dbrType != ca_field_type(arg.chid)) {
/* Size or type changed, clear everything and let the next call
to dbCaGetLink() and/or dbCaPutLink() reset everything */
if (pca->evidNative) {
ca_clear_event(pca->evidNative);
pca->evidNative = 0;
}
if (pca->evidString) {
ca_clear_event(pca->evidString);
pca->evidString = 0;
}
/* BUG: We have no way to clear any old subscription with the
* originally chosen data type/size. That will continue
* to send us data and will result in an assert() fail.
*/
/* Let next dbCaGetLink and/or dbCaPutLink determine options */
plink->value.pv_link.pvlMask &=
~(pvlOptInpNative | pvlOptInpString |
pvlOptOutNative | pvlOptOutString);
@@ -675,6 +805,7 @@ static void connectionCallback(struct connection_handler_args arg)
}
pca->gotFirstConnection = TRUE;
pca->nelements = ca_element_count(arg.chid);
pca->usedelements = 0;
pca->dbrType = ca_field_type(arg.chid);
if ((plink->value.pv_link.pvlMask & pvlOptInpNative) && !pca->pgetNative) {
link_action |= CA_MONITOR_NATIVE;
@@ -706,15 +837,15 @@ static void eventCallback(struct event_handler_args arg)
struct dbr_time_double *pdbr_time_double;
dbCaCallback monitor = 0;
void *userPvt = 0;
int doScan = 1;
assert(pca);
epicsMutexMustLock(pca->lock);
plink = pca->plink;
if (!plink) goto done;
pca->nUpdate++;
monitor = pca->monitor;
userPvt = pca->userPvt;
precord = plink->value.pv_link.precord;
precord = plink->precord;
if (arg.status != ECA_NORMAL) {
if (precord) {
if (arg.status != ECA_NORDACCESS &&
@@ -728,6 +859,7 @@ static void eventCallback(struct event_handler_args arg)
goto done;
}
assert(arg.dbr);
assert(arg.count<=pca->nelements);
size = arg.count * dbr_value_size[arg.type];
if (arg.type == DBR_TIME_STRING &&
ca_field_type(pca->chid) == DBR_ENUM) {
@@ -735,34 +867,33 @@ static void eventCallback(struct event_handler_args arg)
memcpy(pca->pgetString, dbr_value_ptr(arg.dbr, arg.type), size);
pca->gotInString = TRUE;
} else switch (arg.type){
case DBR_TIME_ENUM:
/* Disable the record scan if we also have a string monitor */
doScan = !(plink->value.pv_link.pvlMask & pvlOptInpString);
/* fall through */
case DBR_TIME_STRING:
case DBR_TIME_SHORT:
case DBR_TIME_FLOAT:
case DBR_TIME_ENUM:
case DBR_TIME_CHAR:
case DBR_TIME_LONG:
case DBR_TIME_DOUBLE:
assert(pca->pgetNative);
memcpy(pca->pgetNative, dbr_value_ptr(arg.dbr, arg.type), size);
pca->usedelements = arg.count;
pca->gotInNative = TRUE;
break;
default:
errMessage(-1, "dbCa: eventCallback Logic Error\n");
errlogPrintf("dbCa: eventCallback Logic Error. dbr=%ld dbf=%d\n",
arg.type, ca_field_type(pca->chid));
break;
}
pdbr_time_double = (struct dbr_time_double *)arg.dbr;
pca->sevr = pdbr_time_double->severity;
pca->stat = pdbr_time_double->status;
memcpy(&pca->timeStamp, &pdbr_time_double->stamp, sizeof(epicsTimeStamp));
if (doScan && precord) {
if (precord) {
struct pv_link *ppv_link = &plink->value.pv_link;
if ((ppv_link->pvlMask & pvlOptCP) ||
((ppv_link->pvlMask & pvlOptCPP) && precord->scan == 0))
scanOnce(precord);
scanLinkOnce(precord, pca);
}
done:
epicsMutexUnlock(pca->lock);
@@ -831,11 +962,11 @@ static void accessRightsCallback(struct access_rights_handler_args arg)
pca->hasWriteAccess = ca_write_access(arg.chid);
if (pca->hasReadAccess && pca->hasWriteAccess) goto done;
ppv_link = &plink->value.pv_link;
precord = ppv_link->precord;
precord = plink->precord;
if (precord &&
((ppv_link->pvlMask & pvlOptCP) ||
((ppv_link->pvlMask & pvlOptCPP) && precord->scan == 0)))
scanOnce(precord);
scanLinkOnce(precord, pca);
done:
epicsMutexUnlock(pca->lock);
}
@@ -862,7 +993,7 @@ static void getAttribEventCallback(struct event_handler_args arg)
getAttributes = pca->getAttributes;
getAttributesPvt = pca->getAttributesPvt;
if (arg.status != ECA_NORMAL) {
dbCommon *precord = plink->value.pv_link.precord;
dbCommon *precord = plink->precord;
if (precord) {
errlogPrintf("dbCa: getAttribEventCallback record %s error %s\n",
precord->name, ca_message(arg.status));
@@ -918,11 +1049,15 @@ static void dbCaTask(void *arg)
break; /* workList is empty */
}
link_action = pca->link_action;
if (link_action&CA_SYNC)
epicsEventMustTrigger((epicsEventId)pca->userPvt); /* dbCaSync() requires workListLock to be held here */
pca->link_action = 0;
if (link_action & CA_CLEAR_CHANNEL) --removesOutstanding;
epicsMutexUnlock(workListLock); /* Give back immediately */
if (link_action&CA_SYNC)
continue;
if (link_action & CA_CLEAR_CHANNEL) { /* This must be first */
dbCaLinkFree(pca);
caLinkDec(pca);
/* No alarm is raised. Since link is changing so what? */
continue; /* No other link_action makes sense */
}
@@ -951,11 +1086,11 @@ static void dbCaTask(void *arg)
assert(pca->pputNative);
if (pca->putType == CA_PUT) {
status = ca_array_put(
pca->dbrType, pca->nelements,
pca->dbrType, pca->putnelements,
pca->chid, pca->pputNative);
} else if (pca->putType==CA_PUT_CALLBACK) {
status = ca_array_put_callback(
pca->dbrType, pca->nelements,
pca->dbrType, pca->putnelements,
pca->chid, pca->pputNative,
putComplete, pca);
} else {
@@ -1005,17 +1140,16 @@ static void dbCaTask(void *arg)
}
}
if (link_action & CA_MONITOR_NATIVE) {
size_t element_size;
element_size = dbr_value_size[ca_field_type(pca->chid)];
epicsMutexMustLock(pca->lock);
pca->pgetNative = dbCalloc(pca->nelements, element_size);
pca->elementSize = dbr_value_size[ca_field_type(pca->chid)];
pca->pgetNative = dbCalloc(pca->nelements, pca->elementSize);
epicsMutexUnlock(pca->lock);
status = ca_add_array_event(
ca_field_type(pca->chid)+DBR_TIME_STRING,
ca_element_count(pca->chid),
pca->chid, eventCallback, pca, 0.0, 0.0, 0.0,
&pca->evidNative);
dbf_type_to_DBR_TIME(ca_field_type(pca->chid)),
0, /* dynamic size */
pca->chid, eventCallback, pca, 0.0, 0.0, 0.0, 0);
if (status != ECA_NORMAL) {
errlogPrintf("dbCaTask ca_add_array_event %s\n",
ca_message(status));
@@ -1027,8 +1161,7 @@ static void dbCaTask(void *arg)
pca->pgetString = dbCalloc(1, MAX_STRING_SIZE);
epicsMutexUnlock(pca->lock);
status = ca_add_array_event(DBR_TIME_STRING, 1,
pca->chid, eventCallback, pca, 0.0, 0.0, 0.0,
&pca->evidString);
pca->chid, eventCallback, pca, 0.0, 0.0, 0.0, 0);
if (status != ECA_NORMAL) {
errlogPrintf("dbCaTask ca_add_array_event %s\n",
ca_message(status));

View File

@@ -1,20 +1,17 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* Copyright (c) 2015 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 Versions 3.13.7
* and higher are distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* dbCa.h */
/* dbCa.h */
#ifndef INCdbCah
#define INCdbCah
#include "shareLib.h"
#include "epicsTime.h"
#include "link.h"
#include "dbLink.h"
#ifdef __cplusplus
extern "C" {
@@ -29,48 +26,60 @@ epicsShareFunc void dbCaRun(void);
epicsShareFunc void dbCaPause(void);
epicsShareFunc void dbCaShutdown(void);
struct dbLocker;
epicsShareFunc void dbCaAddLinkCallback(struct link *plink,
dbCaCallback connect, dbCaCallback monitor, void *userPvt);
#define dbCaAddLink(plink) dbCaAddLinkCallback((plink), 0, 0, 0)
epicsShareFunc void dbCaRemoveLink(struct link *plink);
epicsShareFunc long dbCaAddLink(struct dbLocker *locker, struct link *plink, short dbfType);
epicsShareFunc void dbCaRemoveLink(struct dbLocker *locker, struct link *plink);
epicsShareFunc long dbCaGetLink(struct link *plink,
short dbrType, void *pbuffer, epicsEnum16 *pstat, epicsEnum16 *psevr,
long *nRequest);
short dbrType, void *pbuffer, long *nRequest);
epicsShareFunc long dbCaGetAttributes(const struct link *plink,
dbCaCallback callback, void *userPvt);
epicsShareFunc long dbCaPutLinkCallback(struct link *plink,
short dbrType, const void *pbuffer,long nRequest,
dbCaCallback callback, void *userPvt);
#define dbCaPutLink(plink, dbrType, pbuffer, nRequest) \
dbCaPutLinkCallback((plink), (dbrType), (pbuffer), (nRequest), 0, 0)
epicsShareFunc int dbCaIsLinkConnected(const struct link *plink);
epicsShareFunc void dbCaScanFwdLink(struct link *plink);
/* The following are available after the link is connected*/
epicsShareFunc long dbCaGetNelements(const struct link *plink,
long *nelements);
#define dbCaGetSevr(plink, severity) \
dbCaGetAlarm((plink), NULL, (severity))
epicsShareFunc long dbCaGetAlarm(const struct link *plink,
epicsEnum16 *status, epicsEnum16 *severity);
epicsShareFunc long dbCaGetTimeStamp(const struct link *plink,
epicsTimeStamp *pstamp);
epicsShareFunc int dbCaGetLinkDBFtype(const struct link *plink);
/*The following are available after attribute request is complete*/
epicsShareFunc long dbCaGetAttributes(const struct link *plink,
dbCaCallback callback, void *userPvt);
epicsShareFunc long dbCaGetControlLimits(const struct link *plink,
double *low, double *high);
epicsShareFunc long dbCaGetGraphicLimits(const struct link *plink,
double *low, double *high);
epicsShareFunc long dbCaGetAlarmLimits(const struct link *plink,
double *lolo, double *low, double *high, double *hihi);
epicsShareFunc long dbCaGetPrecision(const struct link *plink,
short *precision);
epicsShareFunc long dbCaGetUnits(const struct link *plink,
char *units, int unitsSize);
epicsShareFunc long dbCaPutLink(struct link *plink,short dbrType,
const void *pbuffer,long nRequest);
extern struct ca_client_context * dbCaClientContext;
#ifdef EPICS_DBCA_PRIVATE_API
epicsShareFunc void dbCaSync(void);
epicsShareFunc unsigned long dbCaGetUpdateCount(struct link *plink);
#endif
/* These macros are for backwards compatibility */
#define dbCaIsLinkConnected(link) \
dbIsLinkConnected(link)
#define dbCaGetLinkDBFtype(link) \
dbGetLinkDBFtype(link)
#define dbCaGetNelements(link, nelements) \
dbGetNelements(link, nelements)
#define dbCaGetSevr(link, sevr) \
dbGetAlarm(link, NULL, sevr)
#define dbCaGetAlarm(link, stat, sevr) \
dbGetAlarm(link, stat, sevr)
#define dbCaGetTimeStamp(link, pstamp) \
dbGetTimeStamp(link, pstamp)
#define dbCaGetControlLimits(link, low, high) \
dbGetControlLimits(link, low, high)
#define dbCaGetGraphicLimits(link, low, high) \
dbGetGraphicLimits(link, low, high)
#define dbCaGetAlarmLimits(link, lolo, low, high, hihi) \
dbGetAlarmLimits(link, lolo, low, high, hihi)
#define dbCaGetPrecision(link, prec) \
dbGetPrecision(link, prec)
#define dbCaGetUnits(link, units, unitSize) \
dbGetUnits(link, units, unitSize)
#define dbCaScanFwdLink(link) \
dbScanFwdLink(link)
#ifdef __cplusplus
}
#endif

View File

@@ -6,14 +6,11 @@
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* dbCaPvt.h */
/****************************************************************
*
* Current Author: Bob Dalesio
* Contributing Author: Marty Kraimer
* Date: 08APR96
*
****************************************************************/
/* dbCaPvt.h
*
* Original Authors: Bob Dalesio, Marty Kraimer
*
*/
#ifndef INC_dbCaPvt_H
#define INC_dbCaPvt_H
@@ -32,63 +29,68 @@
#define CA_MONITOR_NATIVE 0x10
#define CA_MONITOR_STRING 0x20
#define CA_GET_ATTRIBUTES 0x40
#define CA_SYNC 0x1000
/* write type */
#define CA_PUT 0x1
#define CA_PUT_CALLBACK 0x2
typedef struct caLink
{
ELLNODE node;
epicsMutexId lock;
struct link *plink;
char *pvname;
chid chid;
short link_action;
/* The following have new values after each data event*/
epicsEnum16 sevr;
epicsEnum16 stat;
epicsTimeStamp timeStamp;
/* The following have values after connection*/
short dbrType;
long nelements;
char hasReadAccess;
char hasWriteAccess;
char isConnected;
char gotFirstConnection;
/* The following are for dbCaAddLinkCallback */
dbCaCallback connect;
dbCaCallback monitor;
void *userPvt;
/* The following are for write request */
short putType;
dbCaCallback putCallback;
void *putUserPvt;
/* The following are for access to additional attributes*/
char gotAttributes;
dbCaCallback getAttributes;
void *getAttributesPvt;
/* The following have values after getAttribEventCallback*/
double controlLimits[2];
double displayLimits[2];
double alarmLimits[4];
short precision;
char units[MAX_UNITS_SIZE]; /* units of value */
/* The following are for handling data*/
void *pgetNative;
char *pgetString;
void *pputNative;
char *pputString;
evid evidNative;
evid evidString;
char gotInNative;
char gotInString;
char gotOutNative;
char gotOutString;
char newOutNative;
char newOutString;
/* The following are for dbcar*/
unsigned long nDisconnect;
unsigned long nNoWrite; /*only modified by dbCaPutLink*/
ELLNODE node;
int refcount;
epicsMutexId lock;
struct link *plink;
char *pvname;
chid chid;
short link_action;
/* The following have new values after each data event*/
epicsEnum16 sevr;
epicsEnum16 stat;
epicsTimeStamp timeStamp;
/* The following have values after connection*/
short dbrType;
size_t elementSize; /* size of one element in pgetNative */
unsigned long nelements; /* PVs max array size */
unsigned long usedelements; /* currently used in pgetNative */
unsigned long putnelements; /* currently used in pputNative */
char hasReadAccess;
char hasWriteAccess;
char isConnected;
char gotFirstConnection;
/* The following are for dbCaAddLinkCallback */
dbCaCallback connect;
dbCaCallback monitor;
void *userPvt;
/* The following are for write request */
short putType;
dbCaCallback putCallback;
void *putUserPvt;
/* The following are for access to additional attributes*/
char gotAttributes;
dbCaCallback getAttributes;
void *getAttributesPvt;
/* The following have values after getAttribEventCallback*/
double controlLimits[2];
double displayLimits[2];
double alarmLimits[4];
short precision;
char units[MAX_UNITS_SIZE]; /* units of value */
/* The following are for handling data*/
void *pgetNative;
char *pgetString;
void *pputNative;
char *pputString;
char gotInNative;
char gotInString;
char gotOutNative;
char gotOutString;
char newOutNative;
char newOutString;
unsigned char scanningOnce;
/* The following are for dbcar*/
unsigned long nDisconnect;
unsigned long nNoWrite; /*only modified by dbCaPutLink*/
unsigned long nUpdate;
}caLink;
#endif /* INC_dbCaPvt_H */

View File

@@ -87,10 +87,10 @@ long dbcar(char *precordname, int level)
!dbIsAlias(pdbentry)) {
pdbRecordType = pdbentry->precordType;
precord = (dbCommon *)pdbentry->precnode->precord;
dbScanLock(precord);
for (j=0; j<pdbRecordType->no_links; j++) {
pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->link_ind[j]];
plink = (DBLINK *)((char *)precord + pdbFldDes->offset);
dbLockSetGblLock();
if (plink->type == CA_LINK) {
ncalinks++;
pca = (caLink *)plink->value.pv_link.pvt;
@@ -135,8 +135,8 @@ long dbcar(char *precordname, int level)
}
}
}
dbLockSetGblUnlock();
}
dbScanUnlock(precord);
if (precordname) goto done;
}
status = dbNextRecord(pdbentry);
@@ -189,10 +189,8 @@ void dbcaStats(int *pchans, int *pdiscon)
dbFldDes *pdbFldDes = pdbRecordType->papFldDes[i];
plink = (DBLINK *)((char *)precord + pdbFldDes->offset);
if (plink->type == CA_LINK) {
caLink *pca = (caLink *)plink->value.pv_link.pvt;
ncalinks++;
if (pca && pca->chid && ca_state(pca->chid) == cs_conn) {
if (dbCaIsLinkConnected(plink)) {
nconnected++;
}
}

View File

@@ -19,7 +19,6 @@
#include "cantProceed.h"
#include "epicsAssert.h"
#include "epicsExit.h"
#include "epicsString.h"
#include "errlog.h"
#include "freeList.h"
@@ -455,6 +454,8 @@ static short mapDBFToDBR[DBF_NTYPES] =
/* DBF_USHORT => */DBR_USHORT,
/* DBF_LONG => */DBR_LONG,
/* DBF_ULONG => */DBR_ULONG,
/* DBF_INT64 => */DBR_INT64,
/* DBF_UINT64 => */DBR_UINT64,
/* DBF_FLOAT => */DBR_FLOAT,
/* DBF_DOUBLE => */DBR_DOUBLE,
/* DBF_ENUM, => */DBR_ENUM,
@@ -510,7 +511,7 @@ dbChannel * dbChannelCreate(const char *name)
paddr->dbr_field_type = mapDBFToDBR[dbfType];
if (paddr->special == SPC_DBADDR) {
struct rset *prset = dbGetRset(paddr);
rset *prset = dbGetRset(paddr);
/* Let record type modify paddr */
if (prset && prset->cvt_dbaddr) {
@@ -532,7 +533,7 @@ dbChannel * dbChannelCreate(const char *name)
paddr->dbr_field_type = DBR_CHAR;
} else if (dbfType >= DBF_INLINK && dbfType <= DBF_FWDLINK) {
/* Clients see a char array, but keep original dbfType */
paddr->no_elements = PVNAME_STRINGSZ + 12;
paddr->no_elements = PVLINK_STRINGSZ;
paddr->field_size = 1;
paddr->dbr_field_type = DBR_CHAR;
} else {

View File

@@ -26,7 +26,6 @@
#endif
#include "compilerDependencies.h"
#include "epicsMemory.h"
#ifdef dbChannelIOh_restore_epicsExportSharedSymbols
# define epicsExportSharedSymbols

118
src/ioc/db/dbChannelNOOP.h Normal file
View File

@@ -0,0 +1,118 @@
#ifndef DBCHANNELNOOP_H
#define DBCHANNELNOOP_H
#include <string.h>
#include <string>
#include "cacIO.h"
#include "caerr.h"
/** @brief A channel which never connects
*
* Used when dbCa is placed in isolated mode for unittests
*/
class dbChannelNOOP : public cacChannel
{
std::string myname;
public:
dbChannelNOOP(const char *name, cacChannelNotify &notify)
:cacChannel(notify)
,myname(name)
{}
virtual void destroy (
CallbackGuard & /*callbackGuard*/,
epicsGuard < epicsMutex > & /*mutualExclusionGuard*/ )
{
delete this; // goodbye cruel world
}
virtual unsigned getName (
epicsGuard < epicsMutex > &,
char * pBuf, unsigned bufLen ) const throw ()
{
const char* name = myname.c_str();
if(bufLen>myname.size()+1) {
bufLen=myname.size()+1;
}
memcpy(pBuf, name, bufLen);
pBuf[--bufLen] = '\0';
return bufLen;
}
// !! deprecated, avoid use !!
virtual const char * pName (
epicsGuard < epicsMutex > & guard ) const throw ()
{return myname.c_str();}
virtual void show (
epicsGuard < epicsMutex > &,
unsigned level ) const
{}
virtual void initiateConnect (
epicsGuard < epicsMutex > & )
{}
virtual unsigned requestMessageBytesPending (
epicsGuard < epicsMutex > & /*mutualExclusionGuard*/ )
{return 0;}
virtual void flush (
epicsGuard < epicsMutex > & /*mutualExclusionGuard*/ )
{}
virtual ioStatus read (
epicsGuard < epicsMutex > &mut,
unsigned type, arrayElementCount count,
cacReadNotify &notify, ioid * = 0 )
{
notify.exception(mut, ECA_NORDACCESS, "dbChannelNOOP", type, count);
return iosSynch;
}
virtual void write (
epicsGuard < epicsMutex > &,
unsigned type, arrayElementCount count,
const void *pValue )
{}
virtual ioStatus write (
epicsGuard < epicsMutex > &mut,
unsigned type, arrayElementCount count,
const void */*pValue*/, cacWriteNotify & notify, ioid * = 0 )
{
notify.exception(mut, ECA_NOWTACCESS, "dbChannelNOOP", type, count);
return iosSynch;
}
virtual void subscribe (
epicsGuard < epicsMutex > &mut, unsigned type,
arrayElementCount count, unsigned /*mask*/, cacStateNotify & notify,
ioid * = 0 )
{
// should never subscribe
notify.exception(mut, ECA_BADMASK, "dbChannelNOOP", type, count);
}
virtual void ioCancel (
CallbackGuard & callbackGuard,
epicsGuard < epicsMutex > & mutualExclusionGuard,
const ioid & )
{}
virtual void ioShow (
epicsGuard < epicsMutex > &,
const ioid &, unsigned level ) const
{}
virtual short nativeType (
epicsGuard < epicsMutex > & ) const
{return 0;} // DBR_STRING
virtual arrayElementCount nativeElementCount (
epicsGuard < epicsMutex > & ) const
{return 1;}
};
#endif // DBCHANNELNOOP_H

Some files were not shown because too many files have changed in this diff Show More