Compare commits

...

315 Commits

Author SHA1 Message Date
Ralph Lange
b319b4722f Update version to 3.15.6-rc1 2018-10-05 15:21:58 +02:00
Ralph Lange
b4cc5fdf4b doc: update release checklist 2018-10-05 15:21:57 +02:00
Ralph Lange
d35835659c libCom/osi: Add epicsStdio functions to std namespace; allow to skip macro magic
(fixes lp:1786927)
2018-10-05 10:54:10 +02:00
Andrew Johnson
cbb13bf6b1 Darwin: Don't link using -flat_namespace 2018-09-18 10:22:29 -05:00
Andrew Johnson
150d764d28 Merge 3.14.12.8 (+ the Travis fix) into 3.15 2018-09-17 16:15:55 -05:00
Andrew Johnson
7dd1ea4cab GNU Make 3.81 (as used on Travis) doesn't have 'undefine' 2018-09-17 10:24:51 -05:00
Andrew Johnson
922ed30136 Set EPICS_DEV_SNAPSHOT for the final 3.14.12.8 release 2018-09-14 13:44:05 -05:00
Andrew Johnson
9f9f119e7e Release notes about iocLogServer 2018-09-14 13:21:06 -05:00
Andrew Johnson
d8214a4531 Merge Martin Konrad's fix-logserver-file-limit branch into 3.14 2018-09-14 12:24:14 -05:00
Andrew Johnson
120b100e7e startup: Fix EHA argument quoting per J. Lewis Muir 2018-09-14 12:15:29 -05:00
Andrew Johnson
949e9d788a Make startup/EpicsHostArch script executable 2018-09-14 11:23:14 -05:00
Martin Konrad
27c6e6a385 Make EpicsHostArch compatible with sh 2018-09-14 09:12:10 -04:00
Andrew Johnson
4b59476170 Merge branch 'tidy-startup' into 3.14 2018-09-13 16:49:21 -05:00
Andrew Johnson
526b565c6b configure/CONFIG: Undefine EHA after use 2018-09-10 18:19:03 -05:00
Andrew Johnson
1b7b2bcceb Update README's list of files 2018-09-10 18:16:16 -05:00
Andrew Johnson
49c925d064 Fix shebang line in makeInstallDir.pl 2018-09-10 16:08:19 -05:00
Ralph Lange
6a2ed4b333 libcom/osi/windows: log errors using fprintf() instead of pop-up
(fixes lp:1785712)
2018-09-05 21:47:25 +02:00
Andrew Johnson
d3bcf5737f Latest Xcode also doesn't like compiling system() for iOS 2018-08-17 14:57:22 -05:00
Andrew Johnson
6c5505ad3e osiClockTime again: Don't compile ClockTimeSync() on iOS either 2018-08-17 13:48:00 -05:00
Andrew Johnson
4247d98b08 Add fix to Release Notes 2018-08-17 13:25:18 -05:00
Andrew Johnson
13735a8088 Fix for lp: #1786320
A dbCa link that reads an enum as a string subscribes to the link target
twice, once as DBR_TIME_ENUM and again as DBR_TIME_STRING. This change
prevents ENUM updates from triggering CP/CPP record processing if there
is also a STRING subscription for this link.
2018-08-17 13:18:47 -05:00
Andrew Johnson
58d4242b68 osiClockTime: Only call clock_setting() on embedded OSs
An update to Apple's XCode broke the iOS build because they have
added Posix CLOCK_REALTIME support since this code was written and
now if you compile a call to clock_settime() it stops the build.
2018-08-17 13:09:33 -05:00
Martin Konrad
8e42f516b0 iocLogserver: allow log file limit to be disabled
According to the Application Developer's Guide setting the environment
variable EPICS_IOC_LOG_FILE_LIMIT=0 should disable the limit on the
file size.
2018-08-13 18:16:26 -04:00
Andrew Johnson
9051cdbb34 Added a simpler startup/EpicsHostArch for backwards-compatibility
Many downstream modules seem to be using the EpicsHostArch script in
their CI build scripts and would break if we remove that. I created
a new version that finds and execs the Perl script directly.

Also reworded and expanded the Release Notes about the EpicsHostArch
scripts.
2018-08-10 15:20:29 -05:00
Andrew Johnson
8ffea9de27 Remove macLib warning indicators
Only add ',undefined' tags to macLib output when we aren't
suppressing warnings, e.g. using msi's -V flag.
2018-08-10 14:12:19 -05:00
Andrew Johnson
2548a37267 Update/clean up EpicsHostArch.pl 2018-08-08 16:53:32 -05:00
Andrew Johnson
1dc1b25aaa caget.pl: Add missing acks and ackt metadata to display output 2018-07-31 17:58:38 -05:00
Andrew Johnson
fb31dd784b recGbl: Prevent record alarm severities > INVALID_ALARM 2018-07-31 16:30:11 -05:00
Andrew Johnson
fe7260e263 msi: Source code reformatting, typo fixes, unify messages
Added lots of debug tracing macros.
Release notes.
2018-07-25 00:47:18 -05:00
Andrew Johnson
67e2b74758 Fix for lp: #1503661
Delete output file if parse errors found in substitution file
2018-07-25 00:31:48 -05:00
Andrew Johnson
c09b6e2f1b libCom: Add and use a -o<filename> option to e_flex
Note that like the -S option the filename must follow immediately in
the same command-line argument with no space.
2018-07-21 01:47:33 -05:00
Andrew Johnson
45be2306bd Add missing includes for db_post_events() 2018-07-21 01:04:05 -05:00
Andrew Johnson
6027f906c3 Merge documentation changes from 3.14 into 3.15 2018-07-20 23:29:47 -05:00
Andrew Johnson
ec351c5e2f Fix for lp: #1730727
Post monitors on all array-length record fields (often NORD)
when their values get changed.
2018-07-20 23:10:34 -05:00
89870e2817 Remove trailing space in license of startup/unix.* 2018-07-20 17:47:39 -05:00
4e9cf72d71 Remove execute file mode bit on EpicsHostArch.pl 2018-07-20 17:45:47 -05:00
80869a0868 Rewrite startup/windows.bat
Remove extraneous things unrelated to EPICS Base.

Make it behave consistently with the other startup scripts.

Make it easy to configure both for a human and a program.
2018-07-20 17:43:01 -05:00
998fa984ba Rewrite startup/win32.bat
Remove extraneous things unrelated to EPICS Base.

Make it behave consistently with the other startup scripts.

Make it easy to configure both for a human and a program.
2018-07-20 17:39:29 -05:00
31844af88e Rewrite startup/unix.csh
Remove extraneous things unrelated to EPICS Base.

Make it behave consistently with the other startup scripts.

Make it easy to configure both for a human and a program.
2018-07-20 17:29:47 -05:00
8f161f9463 Rewrite startup/unix.sh
Remove extraneous things unrelated to EPICS Base.

Make it behave consistently with the other startup scripts.

Make it easy to configure both for a human and a program.
2018-07-20 17:18:22 -05:00
e0399478ad Remove startup/cygwin.bat
Cygwin is no longer supported for Microsoft API builds, so remove it.
2018-07-20 17:14:43 -05:00
Andrew Johnson
2a2a1e54ac Post-tag version number update 2018-07-19 12:35:40 -05:00
Andrew Johnson
20d2cff501 Update version number to 3.14.12.8-rc1 2018-07-19 12:31:52 -05:00
Andrew Johnson
860ce156a2 Documentation updates for 3.14.12.8 2018-07-19 12:20:41 -05:00
Andrew Johnson
0f21196670 Merge 3.14 branch into 3.15 2018-07-13 13:23:11 -05:00
Andrew Johnson
31fc35fbe8 dbCa: Fix for lp: #541221
I'd looked at this a few times since it was reported, but never
actually fixed the bug I described in the comments. Apparently
the only thing left to do was to store the eventId and use it to
clear the subscription when we saw a type-change to a PV.
2018-07-13 13:05:54 -05:00
Andrew Johnson
f892731b3f Fix epicsCalcTest for gcc 7.1.0 on minGW
Another case where the compile-time evaluation returns +1
but at run-time isnan() returns -1.
2018-06-29 15:03:45 -05:00
ab493264b2 Make EpicsHostArch.pl print newline
Print a newline after the EPICS host architecture spec.  This is typical
for a UNIX-like program (e.g., date).
2018-06-26 17:56:58 -05:00
68779943eb Remove execute file mode bit 2018-06-26 16:34:04 -05:00
7a5ff26984 Remove EpicsHostArch 2018-06-26 16:20:07 -05:00
eae59183cc Rename Site.{cshrc,profile} to unix.{csh,sh} 2018-06-26 16:09:04 -05:00
Andrew Johnson
8144d2ea01 Add HOWTO: Converting Wiki Record Reference to POD 2018-06-26 14:47:59 -05:00
Andrew Johnson
b32629c3bf Start release notes for tidy-startup branch. 2018-06-26 11:23:35 -05:00
Andrew Johnson
220e404203 Move EpicsHostArch.pl into src/tools, install to lib/perl 2018-06-26 11:23:15 -05:00
Andrew Johnson
8f55a1307d startup: Update win*.bat files 2018-06-22 14:54:06 -05:00
Ralph Lange
e459e8bdd4 cas: don't spin on zero-length search requests
(fix lp:1743321)
2018-06-07 11:32:16 +02:00
Ralph Lange
b558bd9b16 Cherry-picking e794639e from 3.15
(lp:1730982 lp:1762543)
2018-06-07 11:21:04 +02:00
Michael Davidsaver
3c16c3c0da Cherry-picking d2b0e920 from 3.15
(closes lp:1773373)
2018-06-07 11:07:29 +02:00
Andrew Johnson
a9d7f7be13 Template iocBoot/ioc Makefile fix for Unix-like OSs
Fixes lp: #1766349
2018-06-04 23:14:45 -05:00
Andrew Johnson
23c4eb42a3 Perl s/use vars/our/ 2018-05-28 17:31:16 -05:00
Andrew Johnson
6d7f70f200 Merge changes from 3.14 branch into 3.15 2018-05-28 17:00:35 -05:00
Andrew Johnson
67844bacc3 Perl s/use vars/our/ 2018-05-28 16:13:14 -05:00
Ralph Lange
7e7d230d8c templates: fix warnings for xxxRecord.c in exampleApp
(fixes #1772833)
2018-05-23 09:24:56 +02:00
Andrew Johnson
c1ece40f41 Updated Release Notes for Base-3.14.12.8 2018-05-19 22:42:23 -05:00
Andrew Johnson
a732539eee epicsMath.h defines 'finite()' not 'isfinite()' 2018-05-19 21:14:36 -05:00
Ralph Lange
3bc0805a89 rec: fix missing includes in longin/longout 2018-05-18 09:54:42 +02:00
Ralph Lange
c72e35c769 Merge Ralph's fix-1770292 branch into 3.14 2018-05-17 17:16:07 +02:00
Ralph Lange
2d9c5e99a1 db: correctly convert NaN alarm levels to integers
(fixes lp #1771298)
2018-05-15 11:18:11 +02:00
Ralph Lange
ca22d50831 rec: consistent get_alarm_double() for longin/longout
(fixes lp #1770292)
2018-05-15 11:18:10 +02:00
Michael Davidsaver
4972803ce2 scanEventTest: use testSyncCallback() 2018-05-14 10:49:49 -07:00
Michael Davidsaver
3b7e348a8c dbUnitTest.h add callback sync. and global mutex
Add testSyncCallback() to wait for in queued and
in-progress callbacks to complete.

Also add testGlobalLock() to help tests avoid
use after free when destroying sync. primitives.
2018-05-14 10:49:49 -07:00
Michael Davidsaver
00a974ce52 callback.h: add epicsCallback alternative to CALLBACK
Add epicsCallback as an IDE friendly alternative to CALLBACK.

IDEs like qtcreator have long been confused by the use
of CALLBACK, a name which has long been used by other libraries,
which prevents code using it from being parsed correctly.
2018-05-14 10:49:49 -07:00
Michael Davidsaver
490c504736 scanEventTest: use dbUnitTest.h for IOC lifecycle 2018-05-14 10:49:49 -07:00
Andrew Johnson
49371cfe00 Fix RTEMS build in src/std/rec/test
Also back-ported Michael's change from commit b9b8cde5f6 to avoid
using callocMustSucceed() in eventNameToHandle()
2018-05-12 22:25:15 -05:00
Andrew Johnson
06ad4a0d70 Merge Bruce Hill's pv-name-in-ca-error-msgs branch into 3.15
Actually this is fixing CAS error messages.
I added the additional changes suggested by Ralph in his code-review.
2018-05-12 21:37:44 -05:00
Andrew Johnson
a2ae07dfcd Merge Dirk Zimoch's named-events-backward-compatibility branch into 3.15 2018-05-12 21:15:26 -05:00
Andrew Johnson
b539ced6d5 Merge J. Lewis Muir's doc-filters-typo branch into 3.15 2018-05-12 20:54:20 -05:00
Andrew Johnson
1b332361e7 Merge changes from 3.14 into 3.15 2018-05-12 20:47:54 -05:00
Andrew Johnson
5cb91d9f6d Merge Ben Franksen's deadlock_warning branch into 3.14 2018-05-12 20:20:30 -05:00
Andrew Johnson
116c90c2ea Reformatting, no code changes 2018-05-03 14:40:12 -05:00
Andrew Johnson
3f3696fb91 dbStatic: Prevent modifying a NAME field using a DB file
Fixes LP: #1597809
2018-05-03 14:28:44 -05:00
Benjamin Franksen
91ce807e8b Fix for lp: #1751380
Add warnings about possible deadlock to the docs for ca_clear_channel,
ca_clear_subscription, and ca_context_destroy.
2018-04-11 12:58:28 +02:00
Andrew Johnson
3d88316eab Merge 3.14 into 3.15 (MSVC absolute filenames fix) 2018-03-26 16:49:28 -05:00
Andrew Johnson
b9443f8813 Tell MSVC to use absolute filenames in diagnostics (-FC flag) 2018-03-23 11:39:53 -05:00
Andrew Johnson
d8802c8b24 Merge 3.14 into 3.15 2018-03-15 17:46:48 -05:00
Andrew Johnson
b7d4609e57 Merge Bruce Hill's camonitor-server-relative-ts-bug-3.14 branch 2018-03-15 17:33:32 -05:00
Andrew Johnson
7b5b23f6d3 Merge 3.14 into 3.15 2018-03-15 17:11:20 -05:00
Andrew Johnson
c8a7e1597d VxWorks Timezone updates
Remove 2017; fix hour in MET settings
2018-03-15 10:57:55 -05:00
Andrew Johnson
8333338f99 Merge 3.14 into 3.15 2018-03-14 16:08:07 -05:00
Andrew Johnson
ceaff61c09 Pull in the podToHtml.pl script and rules from 3.15
This lets src/cap5 build with Perl installations that lack Perl's
podchecker and pod2html scripts (e.g. Fedora 27).
2018-03-14 14:12:12 -05:00
Andrew Johnson
2307e94d1c Rules for building bootable TESTPROD_RTEMS targets
Previously if you wanted a .boot file it had to be installed.
2018-03-12 16:34:54 -05:00
Bruce Hill
05a3699b49 Update pcas CA error msgs to include the pv name for easier debugging. 2018-03-09 21:23:43 -08:00
Andrew Johnson
be8f35d782 Fix for lp: #1754298
Cleaned up and reformatted since Dirk's original.
2018-03-09 12:46:46 -06:00
Bruce Hill
6cc623a7b4 Fixed camonitor server side relative timestamps bug
tsFirst needs to get initialized from the first server side
timestamp instead of the client side tsNow.
2018-03-08 01:40:11 -08:00
2b4a9632b7 update RELEASE_NOTES for named event fix 2018-03-07 14:51:38 +01:00
396cf4ee3f remove special handling for inf and nan events 2018-03-07 14:49:12 +01:00
Andrew Johnson
a9764c8f62 tools/caput: Report errors from ca_array_put*()
Fixes LP: #1747983
2018-03-04 15:51:39 -06:00
Andrew Johnson
98d9ea4545 ca/client: Catch by reference, missing '&' 2018-03-04 15:45:15 -06:00
Andrew Johnson
8eb4eec7d2 Corrected fix from Bruce Hill's Github PR#19 2018-03-03 17:17:34 -06:00
Andrew Johnson
98930eebc4 strcpy() -> strncpy() changes from Bruce Hill
Also added some additional static assertions for string field sizes.
2018-03-03 00:12:59 -06:00
e50c468512 moved scanEventTest from src/ioc/db/test to src/std/rec/test 2018-02-26 11:41:54 +01:00
Andrew Johnson
c18b6f2ccf Deny use of dbgf, dbpf, dbtr, dbtgf and dbtpf before iocInit
Can't use locking dbAccess routines until lock-sets have been calculated.
Fixes LP: #1725248
2018-02-24 20:15:08 -06:00
Andrew Johnson
e41f8bf518 Translate and escape chars in info tag strings
Fixes LP: #1716998
2018-02-24 19:11:54 -06:00
Andrew Johnson
ae548d3400 Remove cantProceed() from dbGetLink() and dbPutLink()
Fixes LP: #1528314
Affects 3.15 branch only.
2018-02-24 17:40:45 -06:00
428a8f57e9 Fix typos in Channel Filters doc 2018-02-20 10:20:37 -06:00
29795656e6 bugfix for soft events >= 256 2018-02-20 09:53:06 +01:00
b2d6b67b06 removed obsolete code in scanpel 2018-02-16 11:03:12 +01:00
1e9826d187 add tests for calculated numeric soft events 2018-02-13 15:36:21 +01:00
0691fc5f57 fix scanEvent test 2018-02-13 14:10:29 +01:00
8a3080c16f added test for named soft events 2018-02-13 13:50:19 +01:00
d19afc73af Updated RELEASE_NOTES.html with soft event fix. 2018-02-12 12:06:12 +01:00
adf5375616 fix scanpel glob matching 2018-02-12 09:01:05 +01:00
Andrew Johnson
550beeab9f More clang warning clean-ups
The short => int change is a UB issue, the second argument to va_start()
must be of a type that does not undergo promotion. See
https://wiki.sei.cmu.edu/confluence/display/cplusplus/EXP58-CPP.+Pass+an+object+of+the+correct+type+to+va_start
2018-02-09 11:29:16 -06:00
Andrew Johnson
bf91275200 Merge clang fixes from 3.14 into 3.15 2018-02-09 11:16:26 -06:00
Andrew Johnson
ac4d5c95ac Clean up some compiler warnings from clang 2018-02-09 10:56:52 -06:00
7d836d9554 some cleanup and scanpel improvement 2018-02-09 16:58:36 +01:00
51e492fbb1 Fix numeric events: any number from 0 up to less than 256 is theated as an integer event. Event 0 is no event. 2018-02-09 14:37:45 +01:00
Andrew Johnson
61296b8cff Merge 3.14 into 3.15
Fix for LP: #1743076
2018-02-05 12:03:28 -06:00
Andrew Johnson
de442e9584 Fix for LP: #1743076
Never zero the CA client context private ID.
2018-02-05 12:02:13 -06:00
Andrew Johnson
ac367398b3 Merge fix for lp: #1747091 from 3.14 into 3.15 2018-02-02 17:49:00 -06:00
Andrew Johnson
713c2d5080 Fix for lp: #1747091
generalTimeGetEvent()
2018-02-02 17:47:35 -06:00
Andrew Johnson
af07016464 Merge 3.14 branch into 3.15
Actually a different fix to Michael's 3.14 commit due to divergent code.
2018-02-01 14:20:47 -06:00
Michael Davidsaver
734d16291f rsrv: buffer for IP too small
An IPv4 address and port number
has 21 characters max.
2018-02-01 09:42:51 -08:00
Andrew Johnson
f1e5e9689b Merge 3.14 branch into 3.15 2018-02-01 11:23:29 -06:00
Andrew Johnson
1454f42a27 Config fix for parallel builds with MSVC 2015 and later
From Mark Rivers and Freddie Akeroyd.
2018-02-01 11:19:08 -06:00
Andrew Johnson
ddbdcf9462 rec/test: Add missing filename to DBDDEPENDS_FILES 2018-01-21 00:44:10 -06:00
Andrew Johnson
729e6fda4d tools: Add some context to the 'Undefined macro' warning
Mark Rivers saw this warning when he forgot to configure and build a
dependent module properly. The additional information given by this
change would have helped him track down the problem faster.
2018-01-19 13:14:13 -06:00
Andrew Johnson
0315e90e6e Revert "tools: Use Carp"
This reverts commit f207b00b05.

None of these warn/die messages request a stack dump since they all
end with \n, but carp & croak ignore that.
2018-01-19 11:06:23 -06:00
Andrew Johnson
66c6aaa44f Merge URL updates from 3.14 branch into 3.15 2018-01-18 23:46:42 -06:00
Andrew Johnson
c830a3a4ee Updated links to new EPICS website at Argonne
Only done for documents that are still present in EPICS 7.
2018-01-18 23:35:09 -06:00
Andrew Johnson
8766ce05aa Fix slow callback test failures.
Slow callbacks no longer cause test failures, now they just emit a
diagnostic. Jenkins on MacOS frequently failed those tests.

We should never test for something that we can't fix.
2018-01-04 11:41:38 -06:00
Ralph Lange
8f62940265 Merge appveyor change from 3.14 2018-01-04 09:03:50 +01:00
Ralph Lange
8a1477ecab appveyor-ci: update APS download URL 2018-01-04 09:00:18 +01:00
Ralph Lange
89cbb95c2c Merge appveyor changes from 3.14 2017-12-19 09:52:15 +01:00
Ralph Lange
006ce1a240 appveyor-ci: remove VS 2008, add VS 2017 2017-12-19 09:39:57 +01:00
Ralph Lange
276dee2c3e appveyor-ci: use curl for download of make.zip 2017-12-19 09:39:10 +01:00
Andrew Johnson
98a2871727 Reset SNAPSHOT to -DEV after tagging 3.14.12.7 2017-12-15 16:09:21 -06:00
Andrew Johnson
5ca1bb3bd5 Set SNAPSHOT for 3.14.12.7 final release 2017-12-15 16:06:08 -06:00
Andrew Johnson
f6be3c7f70 Set snapshot to -rc1-DEV 2017-12-08 16:40:08 -06:00
Andrew Johnson
00924dcba0 About to tag 3.14.12.7-rc1 2017-12-08 16:37:03 -06:00
Andrew Johnson
3b0f34e0be Fix recursive check in Release.pm 2017-12-06 16:29:31 -06:00
Andrew Johnson
db005ac3fe RULES_TARGET: Define $(lib)_DIR before it is needed
TESTLIBRARY products were being installed, because an executable
that was linked to one added a dependency assuming it would be in
the INSTALL_LIB directory. The $(lib)_DIR was being set too late
for test libraries, so the fallback location was used instead.
This fix sets $(lib)_DIR for test libraries before any rules use it.
2017-11-17 14:55:50 -06:00
Andrew Johnson
0f0deb8903 Merge fixups/db_close_events into 3.15 2017-11-15 21:23:28 -06:00
Andrew Johnson
baf997193e Merge aSubRecord fixes from 3.14 into 3.15 2017-11-15 21:15:51 -06:00
Andrew Johnson
5278799575 aSubRecord: Copy the right amount of data
Initialize OVLx from VALx with NEVx elements, size from FTVx
2017-11-15 20:59:06 -06:00
Andrew Johnson
031e755303 installEpics.pl: Make temporary install filename more different
A parallel build was seen matching the temporary name in a wildcard.
Now the temporary name both starts and ends differently.
2017-11-11 18:00:57 -06:00
Michael Davidsaver
e794639e31 ioc/db: avoid possible race in db_close_events()
lp:1730982
2017-11-08 14:42:08 -06:00
Michael Davidsaver
2af98c33c9 std/rec: aSub handle INAM changing outputs
Allow EFLG="On Change" to work with INAM.
2017-11-08 14:29:30 -06:00
Andrew Johnson
e38252eecc Fix osiSockOptMcastLoop_t for solaris 2017-10-26 16:29:03 -05:00
Andrew Johnson
31c7d91884 libCom/test/Makefile: Clean up SYS_LIBS var's
Add PROD_SYS_LIBS_solaris global setting
Remove settings for individual tests
2017-10-26 16:28:24 -05:00
Andrew Johnson
42d37eb19a Merge branch 'osiSockTest' into 3.15 2017-10-26 14:30:38 -05:00
Andrew Johnson
cec4f4e24b Unify rsrv socket errors, add missing error string 2017-10-20 14:12:49 -05:00
Andrew Johnson
58460d25b9 Release Notes 2017-10-13 10:57:21 +02:00
Andrew Johnson
9e75b8b32d libcom/test: osiSockTest fix for RTEMS
Instead of 0/1 RTEMS gives 0/32 (32==SO_BROADCAST).
So switch the test to zero/non-zero.
2017-10-13 10:42:19 +02:00
Andrew Johnson
32a6f6c4f1 Fix DBD parsing slow-up with Perl 5.20 and later 2017-10-09 14:45:01 +02:00
Andrew Johnson
169e9f2699 Merged 3.14 changes into 3.15 2017-09-25 15:45:53 -05:00
Andrew Johnson
22debb3532 Fix for LP: #1702298 2017-09-25 15:41:31 -05:00
Andrew Johnson
c441cdd5a4 Adjust comments about EPICS_TIMEZONE 2017-09-25 12:14:48 -05:00
Andrew Johnson
6ee2cc6039 Merged 3.14 branch into 3.15 2017-09-07 17:48:05 -05:00
Andrew Johnson
13fa1e2722 Travis: Use 'make test-results' for more compact output 2017-09-07 17:39:42 -05:00
Andrew Johnson
fad89189da Fix typo in CAref.html 2017-09-07 17:38:58 -05:00
Andrew Johnson
2e4634853c Don't inherit alarm severity from self-referential links
This behavior was present in 3.14 and got lost in my link changes.
Includes a new regression test to detect the broken behavior.
2017-09-02 23:35:07 -05:00
Andrew Johnson
e0757204cc More tests, check both true and false values for options. 2017-08-30 13:58:17 -05:00
Andrew Johnson
78abb25884 Add osiSockOptMcastLoop_t and osiSockTest 2017-08-28 22:36:25 -05:00
Andrew Johnson
73f3e76150 Merged 3.14 branch config changes into 3.15 2017-08-18 17:19:05 -05:00
Andrew Johnson
4ab56518a0 Add readline support to linux-xscale_be rules
Also moves cross-build config to the right host-arch's
2017-08-18 15:14:42 -05:00
Andrew Johnson
80dbc7aeef Clean up the cross-build rules slightly 2017-08-18 15:10:13 -05:00
Andrew Johnson
238f6772bd Dirk's simpler VxWorks version rules 2017-08-18 15:06:38 -05:00
Andrew Johnson
dc9859cee9 Fix RPATH and readline for linux-arm cross-builds 2017-08-18 11:59:17 -05:00
Andrew Johnson
5d5f27a486 Don't set RPATH if STATIC_BUILD=YES 2017-08-18 11:57:50 -05:00
Andrew Johnson
ad6a16d7c4 Update EPICS_TIMEZONE settings, extend to 2022 2017-08-18 11:33:17 -05:00
Michael Davidsaver
111cac8e47 merge 3.14 2017-08-01 17:14:34 +02:00
Michael Davidsaver
5c8e5c52ef rsrv: fix recv() error handling on WIN32
For WIN32 osiSockIoctl_t is unsigned, so

> osiSockIoctl_t nchars = recv(...

is casting signed -> unsigned which treats
errors as success.
2017-08-01 17:02:41 +02:00
Michael Davidsaver
546df1c1f0 rsrv: export CASDEBUG to iocsh 2017-08-01 17:02:41 +02:00
Michael Davidsaver
603331e7a5 rsrv: flush any queued messages before forced disconnect
Avoid loss of various ERROR messages which camessage()
has queued.
2017-08-01 16:44:48 +02:00
Michael Davidsaver
4b272cc0cf rsrv: locking in cas_send_bs_msg()
Must lock around "pclient->send.stk = 0u;"
2017-08-01 16:44:48 +02:00
Michael Davidsaver
619a99bf99 rsrv: missing send lock around send_err() 2017-08-01 16:44:48 +02:00
Michael Davidsaver
1f8cb740f1 rsrv: drop un-commited VERSION message
This is a no-op as cas_commit_msg() isn't called.
A VERSION message is already queued during create_tcp_client().
2017-08-01 16:44:29 +02:00
Michael Davidsaver
322f7a97de rsrv: add some comments 2017-08-01 16:44:29 +02:00
Michael Davidsaver
0fc770166c rsrv: avoid possible overflow in vsend_err()
Accounting of message size doesn't take into account
space used by header of failed message (16 or 24 bytes).
This would allow a theoretical really long error message
to overflow the send buffer by 16 or 24 bytes.
2017-08-01 16:44:08 +02:00
Andrew Johnson
f04f17f9bf Remove vpath for %.pl files
It isn't needed, and in some configurations it causes build failures.
Similar problems could still occur for other file types with a similar
vpath, but it's less likely that other file types would be installed in
an equivalent $(TOP)/../<dir> path.

The original issue with .pl files was caused by an installation of Base
where the parent directory had a bin/<host> soft-link pointing to the
same bin/<host> of a newer installation of the same version of Base, so
it had all the necessary .pl files in it. The vpath allowed the build in
src/tools to search $(TOP)/../bin/<host> when checking the buildInstall
dependency, and since it found those .pl files through the vpath it
didn't bother to install them. When they were run later on in the build
from the $(TOP)/bin/<host>/ path they weren't present so it failed.
2017-07-26 12:02:24 -05:00
Andrew Johnson
1a70855e25 Use static strings for epicsInterruptContextMessage()
The callbackRequest() routine was passing a stack-allocated
string to epicsInterruptContextMessage() but on RTEMS the
pointer is queued without copying the string. This fix uses
static strings for the 3 messages instead.

Fixes LP: #1705219
2017-07-24 11:19:20 -05:00
Andrew Johnson
745109e423 Add loop detection to Release.pm
GNUmake will *usually* spot recursive "include" loops first, but
not if the loop is in another module that we're just checking.
In that case Release.pm eats file descriptors until they run out
without this fix.
2017-06-22 18:38:07 -05:00
Andrew Johnson
b9d2712738 Argh!!! 2017-06-22 17:07:56 -05:00
Andrew Johnson
a69bd833fc More msi.plt retries for Jenkins builds on Windows 2017-06-22 16:45:00 -05:00
Andrew Johnson
630b4f375d Fix 'make test-results' rule for Windows 2017-06-22 16:42:53 -05:00
Andrew Johnson
9d4a90ac34 Fix link initialization from hex constants
Fixes LP: #1699445
Includes regression tests (some of which will fail on 3.16)
2017-06-22 14:29:04 -05:00
Andrew Johnson
83cb50574a Merge bug-fix from 3.14 branch into 3.15 2017-06-20 15:50:49 -05:00
Andrew Johnson
6b5e7da4fd catools: dbr_long_t is only 32 bits wide
Don't print it as a native long.
Fixes LP: #1699332
2017-06-20 15:49:41 -05:00
Andrew Johnson
69d530f1db Cross-build fix for generated .t files
The *target* OS should determine whether to use system or exec.
2017-06-16 15:37:55 -05:00
Andrew Johnson
411a60c32d Add missing link libraries 2017-06-16 12:44:10 -05:00
Andrew Johnson
105e831442 Merge changes from 3.14 branch into 3.15 2017-06-14 10:17:31 -05:00
Andrew Johnson
a1dc16848c configure: Fix include CONFIG_APP_INCLUDE
which needs to happen *after* CONFIG_SITE overrides.
2017-06-14 10:03:43 -05:00
Andrew Johnson
2819d7ea3d Posix epicsEventWaitWithTimeout() max delay
Limit timeouts on Posix to max-out at 10 years.
Adds a test that will fail when that time-out hits Y2038 on
systems where time_t is still a 32-bit integer.
2017-06-14 10:01:23 -05:00
Andrew Johnson
6ef995525a Restore the use of DBL_MAX in timerQueue.cpp 2017-06-09 13:44:30 -05:00
Andrew Johnson
18dee384ec Fix tv_sec casts to use time_t, not long 2017-06-09 12:20:16 -05:00
Andrew Johnson
b369aa67f1 Use 1000 years as 'forever' in timers
DBL_MAX causes problems...
2017-06-08 21:55:12 -05:00
Andrew Johnson
085fab4aed Merge 3.14 branch into 3.15 2017-06-08 09:55:05 -04:00
Andrew Johnson
c853234e01 Remove artificial 60-minute timeout limit (Posix) 2017-06-08 09:53:07 -04:00
Andrew Johnson
1293747cf3 Merge 3.14 branch into 3.15 2017-06-01 16:40:33 -05:00
Andrew Johnson
9c859ffdca Protect casStatsFetch() if called before rsrv_init()
Also ensures clientQ is initialized before creating clientQlock.

Fixes LP: #1694966
2017-06-01 15:37:34 -05:00
Andrew Johnson
29c069db3d Testing msi: Add retries if necessary
Hoping this will fix the annoying problems on Windows Jenkins.
2017-05-31 12:51:39 -05:00
Andrew Johnson
12d22e392f Merge 3.14 branch into 3.15 2017-05-30 17:14:56 -05:00
Andrew Johnson
0dc850f4ec A gitignore pattern for vi on MacOS 2017-05-30 17:13:56 -05:00
Andrew Johnson
98b0f7e48b Merge 3.14 branch into 3.15 2017-05-19 17:34:49 -05:00
Andrew Johnson
672fd16ec8 Add make targets test-results and clean-tests
These are mainly intended for CI builds.
2017-05-19 15:44:15 -05:00
Ralph Lange
dcadeac903 ci: add appveyor configuration 2017-05-19 13:38:39 +09:00
Andrew Johnson
0b3e44747e Merge 3.14 branch into 3.15
# Conflicts:
#	configure/RULES.Db
#	configure/RULES_ARCHS
#	configure/RULES_BUILD
#	documentation/RELEASE_NOTES.html
2017-05-18 17:07:41 -05:00
Andrew Johnson
b7b3dd2b37 Support for 'make junitfiles' target.
The Perl XML::Generator module must be installed to use this.
2017-05-18 16:31:43 -05:00
Andrew Johnson
b14d77dcf2 Fix tools/test/*.plt 'use lib' lines
This allows the tests to work when INSTALL_LOCATION is set.
2017-05-11 15:29:52 -05:00
Andrew Johnson
cb89710bbd Update comments in the configure/RELEASE file 2017-05-11 14:50:00 -05:00
Andrew Johnson
b3bbf67ce8 Add support for a CONFIG_SITE.local file 2017-05-11 14:49:04 -05:00
Xiaoqiang Wang
82396ee3ef fix data size of gdd container type
getDataSizeElement of gdd container returns the number of sub fields.
It has to be called on the "value" field. This fix has already been done
in monitorReponse.
2017-05-10 10:22:13 -05:00
Michael Davidsaver
a7c14ec995 Merge remote-tracking branch 'launchpad/3.14'
* launchpad/3.14:
  ioc/rsrv: bounds check DBR
2017-05-03 16:53:43 -04:00
Michael Davidsaver
e430d097b7 ioc/rsrv: bounds check DBR
avoid array overrun when evaluating dbr_size_n() macro.
2017-05-03 16:49:28 -04:00
Michael Davidsaver
875e4db3f9 Merge remote-tracking branch 'launchpad/3.14'
* launchpad/3.14:
  missing include

Conflicts:
	src/ioc/dbStatic/dbStaticLib.c
2017-05-02 18:38:40 -04:00
Michael Davidsaver
8c8604c503 Merge remote-tracking branch 'launchpad/3.14'
* launchpad/3.14:
  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/ioc/dbStatic/dbStaticLib.c
	src/libCom/osi/epicsAssert.h
2017-05-02 18:31:40 -04:00
Michael Davidsaver
9d7c4434ad rename iocshFind -> iocshFindCommand 2017-05-02 18:23:52 -04:00
Keenan Lang
67e12bca9f Added patch 2017-05-02 18:23:52 -04:00
Keenan Lang
15cb72acbc Changed function outputs to remove pointer to next function. 2017-05-02 18:23:52 -04:00
Keenan Lang
45ed461665 more whitespace 2017-05-02 18:23:52 -04:00
Keenan Lang
3986e43135 whitespace 2017-05-02 18:23:51 -04:00
Keenan Lang
daad3c6995 Added functions to allow access to what functions and variables the ioc shell has registered. 2017-05-02 18:23:51 -04:00
Michael Davidsaver
38be82a154 missing include 2017-05-02 18:22:57 -04:00
Michael Davidsaver
27cd9fd051 ioc/dbStatic: dbFreeBase() don't double free alias'd records
dbFreeBase() has been broken since alias() was introduced.

Traversal of recList in the function assumed that dbDeleteRecord()
remove only the current dbRecordNode.  However, dbDeleteRecord()
called dbDeleteAliases() which removes alias dbRecordNode s.
If this happens (as it often does) to be the node immediately
after the real node, dbFreeBase() will then iterate using
a ellDelete()d node.
2017-05-02 18:04:06 -04:00
Michael Davidsaver
1ffce72a38 ioc/dbStatic: plug leak in dbFreeBase() 2017-05-02 18:02:05 -04:00
Michael Davidsaver
dcac64d50f ioc/dbStatic: whitespace 2017-05-02 18:01:39 -04:00
Andrew Johnson
0bf789db4c Fix indentation warning from GCC 2017-04-28 14:56:18 -05:00
Michael Davidsaver
57cbe61709 libCom/test: errlog test more verbose 2017-04-27 16:53:40 -04:00
Michael Davidsaver
a2ab17a782 libCom: STATIC_ASSERT use c++11 static_assert when possible 2017-04-27 16:52:33 -04:00
Michael Davidsaver
c6910decfc oops 2017-04-27 14:19:15 -04:00
Michael Davidsaver
b01dd38526 std/filter/test: use dbUnitTest 2017-04-27 14:09:41 -04:00
Andrew Johnson
d825f87359 Check for empty PV names in Perl catools 2017-04-27 12:10:27 -05:00
Michael Davidsaver
82ff67a204 travis-ci enable mingw w/ dll 2017-04-27 12:57:01 -04:00
Michael Davidsaver
e751480b06 Merge remote-tracking branch 'launchpad/3.14'
* launchpad/3.14:
  travisci
  catools: Fix SEGFAULT from bad PV names
  typo
2017-04-27 12:55:35 -04:00
Michael Davidsaver
3184371e8d travisci 2017-04-27 12:53:35 -04:00
Andrew Johnson
f2e54be965 catools: Fix SEGFAULT from bad PV names 2017-04-27 10:52:07 -05:00
Jeong Han Lee
c22670cbb0 typo 2017-04-24 21:06:30 -04:00
Andrew Johnson
35385bc688 Merge changes from 3.14 into 3.15
Changes to be committed:
	modified:   src/ioc/db/dbCa.c
	modified:   src/libCom/calc/postfix.h
	modified:   src/libCom/test/epicsCalcTest.cpp
2017-04-24 18:10:53 -05:00
Andrew Johnson
c5decfbd12 Fix for dbCa warning seg-fault
Don't queue an errlog message containing a pointer to a string
that will disappear soon.

Thanks to Matt Pearson for the bug analysis.
2017-04-24 18:03:53 -05:00
Andrew Johnson
e25a2964bc Fix postfix.h macro arg, document 2017-04-21 16:09:36 -05:00
Michael Davidsaver
22b10adf29 ioc/db: testdbGetFieldEqual() detect zero size 2017-04-21 16:14:43 -04:00
Michael Davidsaver
8382367495 libCom/test: epicsCalcTest use exact postifx buffers
exposes INFIX_TO_POSTFIX_SIZE() bug
2017-04-21 16:13:18 -04:00
Andrew Johnson
821fb1302b Merged changes from 3.14 branch into 3.15 2017-04-20 16:57:08 -05:00
Andrew Johnson
64c16c0f6e Cleanup in asLib
Improve error messages.
Remove unnecessary pointer casts.
2017-04-20 16:27:20 -05:00
Andrew Johnson
9f01c47542 Allow whitespace before comments in AS config files
Fixes lp: #1677302
Makes the lexer patterns more like dbStatic.
Handle non-printable invalid characters in input properly.
2017-04-20 16:23:36 -05:00
Andrew Johnson
aca7b44a05 Supress MS warning C4251 2017-04-20 11:42:52 -05:00
Andrew Johnson
b8f542fc0d Add a plan to std/filters/test/syncTest.c 2017-04-18 14:49:40 -05:00
Andrew Johnson
6f9905d060 Fix dbUnitTest.c 2017-04-18 14:48:54 -05:00
Michael Davidsaver
f3841c4767 avoid void* += 2017-04-17 18:58:19 -04:00
Andrew Johnson
4f8fd545fa Merge branch 'fix-async-dns/master' into 3.14 2017-04-17 15:52:10 -05:00
Andrew Johnson
d4552af39b Fix and test for macLib losing error status
Problem found & diagnosed by Mark Rivers.
2017-04-17 11:47:21 -05:00
Michael Davidsaver
0c02c5cb30 update notes 2017-04-15 19:38:56 -04:00
Michael Davidsaver
1f90e98491 libCom/test: ipAddrToAsciiTest skip cleanup unless valgrind is possible 2017-04-15 19:34:04 -04:00
Michael Davidsaver
352fd32c45 libCom/test: add ipAddrToAsciiTest to testHarness 2017-04-12 20:30:23 -04:00
Michael Davidsaver
b624222a0f db/test: dbPutGetTest check dbGet() of long string field 2017-04-06 20:28:04 -04:00
Michael Davidsaver
739a112bec db: dbGet() ensure long string nil and actual string length 2017-04-06 20:28:01 -04:00
Michael Davidsaver
5e082bb75d db/test: dbPutGetTest check for dbGet() attribute crash 2017-04-06 20:27:37 -04:00
Michael Davidsaver
8ebfd0821a db: fix dbGet() for attributes as long string
dbGet() of "rec.RTYP$" with DBF_CHAR and nRequest==1
not handled correctly.  Results in crash.
2017-04-06 20:27:34 -04:00
Michael Davidsaver
fc8d4c2b5f db/test: dbPutGetTest add test for lp:1678494 2017-04-06 20:27:18 -04:00
Michael Davidsaver
1888253093 db: fix dbGet() of link fields as DBF_CHAR
dbGet() DBF_CHAR with nRequest==1 not handled correctly.
Results in crash.
2017-04-06 20:27:13 -04:00
Michael Davidsaver
8edefb9d63 dbUnitTest: add testdbGetArrFieldEqual() 2017-04-06 20:27:03 -04:00
Michael Davidsaver
0f31e35b87 db/test: add dbPutGetTest 2017-04-06 20:25:55 -04:00
Andrew Johnson
5a73ac59a1 Adjusted .gitignore patterns 2017-03-31 12:18:43 -05:00
Andrew Johnson
e0af3e2af5 Adjusted .gitignore patterns 2017-03-31 12:08:03 -05:00
Ralph Lange
5726ca6964 libCom/test: add network libraries for Windows builds 2017-03-31 15:01:51 +02:00
Ralph Lange
f164b14ba1 Moved .bzrignore to .gitignore 2017-03-30 15:43:15 -05:00
Ralph Lange
4c06cdc660 Move .bzrignore to .gitignore 2017-03-30 17:10:52 +02:00
Andrew Johnson
f71102982f Fix "make -q" problems with shared library stubs 2017-03-06 18:46:46 -06:00
Andrew Johnson
d6b0c3041e Merged changes from 3.14 branch to revno 12703 2017-03-06 15:40:28 -06:00
Andrew Johnson
214e9534cc Allow 'make -q' to work with CHECK_RELEASE=NO 2017-03-03 18:18:57 -06:00
Michael Davidsaver
2a0cd00958 libca: lock when removing from msgMultiPVList 2017-02-27 14:48:30 -05:00
Michael Davidsaver
d744b06a28 libca: findOrCreateVirtCircuit() can return w/ piiu==NULL 2017-02-27 11:07:17 -05:00
Michael Davidsaver
048b75304d libCom/test: add ipAddrToAsciiTest 2017-02-25 19:08:46 -05:00
Ben Franksen
aaafb1a5de db: call rset::get_precision with wrong type 2017-02-25 16:42:29 -05:00
Michael Davidsaver
5783823e25 libCom: revise ipAddrToAscii
create multiple light-weight engines to
track transactions by engine and cancel
all transactions when an engine is released.

prior to fix for lp:1527636 this was ensured
for the last/only owner for the engine singleton.
2017-02-23 20:08:46 -05:00
Andrew Johnson
de698f370a Merged Windows fixes from 3.14 branch, to revno 12699 2017-01-30 14:31:04 -06:00
Andrew Johnson
faf691a5be VS2015 starting to dislike '/' for compiler flags 2017-01-30 12:11:29 -06:00
Andrew Johnson
3a0e52fc3f Fix Windows dllPath.bat properly 2017-01-24 14:17:37 -06:00
Andrew Johnson
a105c6f538 Always quote Windows PATH arg's 2017-01-24 11:48:36 -06:00
Andrew Johnson
73eecbb759 Merged ARCH and bind fixes from 3.14 branch, revno 12696 2017-01-23 17:20:51 -06:00
Andrew Johnson
3e58c59377 Fix CA server bind issue from Freddie Akeroyd 2017-01-19 12:33:54 -06:00
Andrew Johnson
b9ae6c3308 Allow ARCH with trailing spaces 2017-01-18 10:59:36 -06:00
Andrew Johnson
3fd659e693 Merged PATH fix from 3.14 branch, revno 12694 2017-01-16 16:12:04 -06:00
Andrew Johnson
7310d78057 Prepend to PATH, not append 2017-01-16 10:46:56 -06:00
Andrew Johnson
dfc1b8ac23 Merged scan-rate protection changes from 3.14 branch, to revno 12693 2017-01-06 17:24:57 -06:00
Andrew Johnson
49e0e23f76 Better protection against bad periodic scan rates 2017-01-06 15:38:03 -06:00
Andrew Johnson
4a0fd0b954 Fix error message 2017-01-05 14:09:03 -06:00
Andrew Johnson
20dda339cc Make *_INC files order-only prerequisites 2017-01-04 16:32:13 -06:00
Andrew Johnson
7ec6be5d14 Update version numbers in documents for 3.15.6 2016-12-13 17:03:54 -06:00
Ralph Lange
eff44268e9 Set version to 3.15.5-DEV, close 3.15.5 chapter in release notes 2016-12-13 15:33:01 +01:00
Ralph Lange
fd53e175b4 Update CONFIG_BASE_VERSION for 3.15.5, remove "not released" from RELEASE_NOTES 2016-12-13 14:25:23 +01:00
Andrew Johnson
85b5551b3b Merged final changes from 3.14.12.6 release 2016-12-09 17:27:35 -06:00
Andrew Johnson
260bc64b59 Set SNAPSHOT back to -DEV 2016-12-09 13:50:17 -06:00
Andrew Johnson
5097ac3230 Set SNAPSHOT for 3.14.12.6 2016-12-09 13:48:55 -06:00
Andrew Johnson
8d7bf52e51 One more cppcheck issue fixed 2016-12-09 11:17:43 -06:00
Andrew Johnson
a13416309c Merged asLib fix from 3.14 branch, to revno 12688 2016-12-08 14:00:52 -06:00
Andrew Johnson
1cb75ebb6e asLib message buffer too small (Freddie Akeroyd) 2016-12-08 13:57:23 -06:00
Andrew Johnson
63b059c35e Resolve additional cppcheck issues; fix iOS build 2016-12-07 17:51:00 -06:00
Andrew Johnson
dba6971e07 Merged changes from 3.14 branch to revno 12687 2016-12-07 16:36:58 -06:00
Andrew Johnson
94397b52fc Resolve some cppcheck errors & warnings 2016-12-07 13:53:26 -06:00
Andrew Johnson
7fe152ce1b Merge Bruce Hill's pcas-deadlock-fix-3.14 branch 2016-12-07 10:43:06 -06:00
Bruce Hill
d3568605ce Fetch nativeCount() in casChannelI constructor to avoid deadlock
if we fetch it from eventSysProcess()
2016-12-06 13:43:59 -08:00
Andrew Johnson
666721c7ad Document caput scalar arg's, update usage docs 2016-12-06 12:16:35 -06:00
Andrew Johnson
c3bb2bf2c2 Merged changes from 3.14 branch to revno 12682 2016-11-30 12:04:00 -06:00
0f7f4710c6 PCAS dynamic array support for GDD container types 2016-11-30 11:58:24 -06:00
Ralph Lange
2841af7069 rec: add promptgroups for OFFS and SHFT of fanout and seq 2016-11-29 14:48:57 +01:00
Andrew Johnson
726d7c6715 Fix chfPluginTest for MS 2015 compiler 2016-11-15 10:34:10 -06:00
Andrew Johnson
f1439f8b1c Fix epicsStdioTest for MS 2015 compiler 2016-11-15 09:56:42 -06:00
Andrew Johnson
aa6e976f92 Add .local includes to makeBaseApp templates 2016-11-04 17:18:14 -05:00
Andrew Johnson
3e0ddbb542 Set snapshot to -rc1-DEV 2016-10-31 18:06:50 -05:00
Andrew Johnson
67daaaa9b7 Set snapshot to -rc1-DEV 2016-10-31 17:06:19 -05:00
Andrew Johnson
a36443557b Set version to 3.14.12.6-rc1 2016-10-31 17:03:35 -05:00
Michael Davidsaver
428268a71e rsrv: avoid strlen() on possible unterminated strings
Detect these w/o risk of SIGSEGV
2014-01-11 10:59:57 -05:00
Michael Davidsaver
746c739769 add epicsStrnLen()
Base currently requires only POSIX 2001 while
strnlen() is part of POSIX 2008.
2014-01-11 10:58:39 -05:00
245 changed files with 6271 additions and 2916 deletions

View File

@@ -1,9 +0,0 @@
./bin
./lib
./db
./dbd
./html
./include
./templates
**/O.*
./QtC-*

14
.gitignore vendored Normal file
View File

@@ -0,0 +1,14 @@
/cfg/
/bin/
/lib/
/db/
/dbd/
/html/
/include/
/templates/
/configure/*.local
O.*/
/QtC-*
*.orig
*.log
.*.swp

32
.travis.yml Normal file
View File

@@ -0,0 +1,32 @@
sudo: false
dist: trusty
language: c
compiler:
- gcc
env:
- CMPLR=gcc
- CMPLR=gcc EXTRA=CMD_CXXFLAGS=-std=c++11
- CMPLR=gcc STATIC=YES
- CMPLR=clang
- CMPLR=clang STATIC=YES
- WINE=32 TEST=NO STATIC=YES
- WINE=32 TEST=NO STATIC=NO
- RTEMS=4.10 TEST=NO
- RTEMS=4.9 TEST=NO
addons:
apt:
packages:
- libreadline6-dev
- libncurses5-dev
- perl
- clang
- g++-mingw-w64-i686
- bison
- flex
- texinfo
- install-info
cache:
directories:
- $HOME/.cache
install: sh ci/travis-prepare.sh </dev/null
script: sh ci/travis-build.sh </dev/null

2
README
View File

@@ -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
http://www.aps.anl.gov/epics/
https://epics.anl.gov/

85
appveyor.yml Normal file
View File

@@ -0,0 +1,85 @@
# AppVeyor configuration for EPICS Base
# Ralph Lange <ralph.lange@gmx.de>
# Copyright (c) 2016-2017 ITER Organization
# Version format
version: base-{branch}-{build}
#---------------------------------#
# repository cloning #
#---------------------------------#
# Called at very beginning, before repo cloning
init:
# Set autocrlf to make batch files work
- git config --global core.autocrlf true
# Set clone depth (do not fetch complete history)
clone_depth: 2
# Skipping commits affecting only specific files
skip_commits:
files:
- 'documentation/*'
- 'templates/*'
- '**/*.html'
- '**/*.md'
#---------------------------------#
# build matrix configuration #
#---------------------------------#
# Build Configurations: dll/static, regular/debug
configuration:
- dynamic
- static
- dynamic-debug
- static-debug
# Environment variables: compiler toolchain
environment:
matrix:
- 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
# Platform: architecture
platform:
- x86
- x64
# Matrix configuration: allow specific failing jobs
matrix:
exclude:
# VS Express installs don't have the 64 bit compiler
- platform: x64
TOOLCHAIN: 10.0
#---------------------------------#
# building & testing #
#---------------------------------#
install:
- cmd: ci/appveyor-prepare.bat
build_script:
- cmd: ci/appveyor-make.bat
test_script:
- cmd: ci/appveyor-make.bat runtests
#---------------------------------#
# notifications #
#---------------------------------#
notifications:
- provider: Slack
incoming_webhook:
secure: RYOm3FIUYeZGjWKaeTVKwq+C3fzK54AKwbmAoECED45mex3lN+8HmrC845a6mg9xPUJ/ND51RopWVaKDD9/UzaM0SO195RQLKqUTIUafiuM=

137
ci/appveyor-make.bat Normal file
View File

@@ -0,0 +1,137 @@
:: Universal build script for AppVeyor (https://ci.appveyor.com/)
:: Environment:
:: TOOLCHAIN - toolchain version [10.0/11.0/12.0/14.0/2017/cygwin/mingw]
:: CONFIGURATION - determines EPICS build [dynamic/static]
:: PLATFORM - architecture [x86/x64]
::
:: All command line args are passed to make
Setlocal EnableDelayedExpansion
set "ST="
if /i "%CONFIGURATION%"=="static" set ST=-static
set OS=64BIT
if "%PLATFORM%"=="x86" set OS=32BIT
echo [INFO] Platform: %OS%
:: Use parallel make, except for 3.14
set "MAKEARGS=-j2 -Otarget"
if "%APPVEYOR_REPO_BRANCH%"=="3.14" set MAKEARGS=
if "%TOOLCHAIN%"=="cygwin" (
set "MAKE=make"
if "%OS%"=="64BIT" (
set "EPICS_HOST_ARCH=cygwin-x86_64"
set "INCLUDE=C:\cygwin64\include;%INCLUDE%"
set "PATH=C:\cygwin64\bin;%PATH%"
echo [INFO] Cygwin Toolchain 64bit
) else (
set "EPICS_HOST_ARCH=cygwin-x86"
set "INCLUDE=C:\cygwin\include;%INCLUDE%"
set "PATH=C:\cygwin\bin;%PATH%"
echo [INFO] Cygwin Toolchain 32bit
)
echo [INFO] Compiler Version
gcc -v
goto Finish
)
if "%TOOLCHAIN%"=="mingw" (
set "MAKE=mingw32-make"
if "%OS%"=="64BIT" (
set "EPICS_HOST_ARCH=windows-x64-mingw"
set "INCLUDE=C:\tools\mingw64\include;%INCLUDE%"
set "PATH=C:\tools\mingw64\bin;%PATH%"
echo [INFO] MinGW Toolchain 64bit
) else (
set "EPICS_HOST_ARCH=win32-x86-mingw"
set "INCLUDE=C:\tools\mingw32\include;%INCLUDE%"
set "PATH=C:\tools\mingw32\bin;%PATH%"
echo [INFO] MinGW Toolchain 32bit
)
echo [INFO] Compiler Version
gcc -v
goto Finish
)
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
if !ERRORLEVEL! NEQ 0 (
call "%VSINSTALL%\VC\vcvarsall.bat" x86_amd64
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
)
goto MSFound
)
if exist "%VSINSTALL%\VC\bin\amd64\vcvars64.bat" (
call "%VSINSTALL%\VC\bin\amd64\vcvars64.bat"
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
) 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
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
if exist "%VSINSTALL%\Common7\Tools\vsvars32.bat" (
call "%VSINSTALL%\Common7\Tools\vsvars32.bat"
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
)
:MSMissing
echo [INFO] Installation for MSVC Toolchain %TOOLCHAIN% / %OS% seems to be missing
exit 1
:MSFound
echo [INFO] Microsoft Visual Studio Toolchain %TOOLCHAIN%
echo [INFO] Compiler Version
cl
:Finish
echo [INFO] EPICS_HOST_ARCH: %EPICS_HOST_ARCH%
echo [INFO] Make version
%MAKE% --version
echo [INFO] Perl version
perl --version
%MAKE% %MAKEARGS% %*

70
ci/appveyor-prepare.bat Normal file
View File

@@ -0,0 +1,70 @@
:: Build script for AppVeyor (https://ci.appveyor.com/)
:: Environment:
:: TOOLCHAIN - Toolchain Version [9.0/10.0/11.0/12.0/14.0/cygwin/mingw]
:: CONFIGURATION - determines EPICS build [dynamic/static, -debug]
:: PLATFORM - "x86" -> use 32bit architecture
::
:: Prepares an Appveyor build by excuting the following steps
:: - Set up configure\CONFIG_SITE for static vs. dynamic build
:: - Install Cygwin / Mingw (TOOLCHAIN setting) in the in the appropriate flavor
:: - Download and install Make-4.1 from EPICS download page
Setlocal EnableDelayedExpansion
set OS=64BIT
if "%PLATFORM%"=="x86" set OS=32BIT
echo [INFO] Platform: %OS%
if "%TOOLCHAIN%"=="cygwin" (
echo.%CONFIGURATION% | findstr /C:"static">nul && (
echo SHARED_LIBRARIES=NO>> configure\CONFIG_SITE
echo STATIC_BUILD=YES>> configure\CONFIG_SITE
echo [INFO] EPICS set up for static build
) || (
echo [INFO] EPICS set up for dynamic build
)
echo.%CONFIGURATION% | findstr /C:"debug">nul && (
echo HOST_OPT=NO>> configure\CONFIG_SITE
echo [INFO] EPICS set up for debug build
) || (
echo [INFO] EPICS set up for optimized build
)
if "%OS%"=="64BIT" (
echo [INFO] Installing Cygwin 64bit and dependencies
@powershell -Command "(new-object net.webclient).DownloadFile('http://www.cygwin.com/setup-x86_64.exe', 'C:\cygwin64\setup-x86_64.exe')"
C:\cygwin64\setup-x86_64.exe -q -P "libreadline-devel,libncursesw-devel"
) else (
echo [INFO] Installing Cygwin 32bit and dependencies
@powershell -Command "(new-object net.webclient).DownloadFile('http://www.cygwin.com/setup-x86.exe', 'C:\cygwin\setup-x86.exe')"
C:\cygwin\setup-x86.exe -q -P "libreadline-devel,libncursesw-devel"
)
)
if "%TOOLCHAIN%"=="mingw" (
echo.%CONFIGURATION% | findstr /C:"static">nul && (
echo SHARED_LIBRARIES=NO>> configure\CONFIG_SITE
echo STATIC_BUILD=YES>> configure\CONFIG_SITE
echo [INFO] EPICS set up for static build
) || (
echo [INFO] EPICS set up for dynamic build
)
echo.%CONFIGURATION% | findstr /C:"debug">nul && (
echo HOST_OPT=NO>> configure\CONFIG_SITE
echo [INFO] EPICS set up for debug build
) || (
echo [INFO] EPICS set up for optimized build
)
if "%OS%"=="64BIT" (
echo [INFO] Installing MinGW 64bit
cinst mingw || cinst mingw
) else (
echo [INFO] Installing MinGW 32bit
cinst mingw --x86 || cinst mingw --x86
)
)
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
cd \tools
"C:\Program Files\7-Zip\7z" e make-4.1.zip

90
ci/travis-build.sh Normal file
View File

@@ -0,0 +1,90 @@
#!/bin/sh
set -e -x
die() {
echo "$1" >&2
exit 1
}
ticker() {
while true
do
sleep 60
date -R
[ -r "$1" ] && tail -n10 "$1"
done
}
CACHEKEY=1
EPICS_HOST_ARCH=`perl src/tools/EpicsHostArch.pl`
[ -e configure/os/CONFIG_SITE.Common.linux-x86 ] || die "Wrong location: $PWD"
case "$CMPLR" in
clang)
echo "Host compiler is clang"
cat << EOF >> configure/os/CONFIG_SITE.Common.$EPICS_HOST_ARCH
GNU = NO
CMPLR_CLASS = clang
CC = clang
CCC = clang++
EOF
;;
*) echo "Host compiler is default";;
esac
if [ "$STATIC" = "YES" ]
then
echo "Build static libraries/executables"
cat << EOF >> configure/CONFIG_SITE
SHARED_LIBRARIES=NO
STATIC_BUILD=YES
EOF
fi
# requires wine and g++-mingw-w64-i686
if [ "$WINE" = "32" ]
then
echo "Cross mingw32"
sed -i -e '/CMPLR_PREFIX/d' configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw
cat << EOF >> configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw
CMPLR_PREFIX=i686-w64-mingw32-
EOF
cat << EOF >> configure/CONFIG_SITE
CROSS_COMPILER_TARGET_ARCHS+=win32-x86-mingw
EOF
fi
# set RTEMS to eg. "4.9" or "4.10"
# requires qemu, bison, flex, texinfo, install-info
if [ -n "$RTEMS" ]
then
echo "Cross RTEMS${RTEMS} for pc386"
install -d /home/travis/.cache
curl -L "https://github.com/mdavidsaver/rsb/releases/download/travis-20160306-2/rtems${RTEMS}-i386-trusty-20190306-2.tar.gz" \
| tar -C /home/travis/.cache -xj
sed -i -e '/^RTEMS_VERSION/d' -e '/^RTEMS_BASE/d' configure/os/CONFIG_SITE.Common.RTEMS
cat << EOF >> configure/os/CONFIG_SITE.Common.RTEMS
RTEMS_VERSION=$RTEMS
RTEMS_BASE=/home/travis/.cache/rtems${RTEMS}-i386
EOF
cat << EOF >> configure/CONFIG_SITE
CROSS_COMPILER_TARGET_ARCHS+=RTEMS-pc386
EOF
# find local qemu-system-i386
export PATH="$HOME/.cache/qemu/usr/bin:$PATH"
echo -n "Using QEMU: "
type qemu-system-i386 || echo "Missing qemu"
EXTRA=RTEMS_QEMU_FIXUPS=YES
fi
make -j2 $EXTRA
if [ "$TEST" != "NO" ]
then
make tapfiles
make -s test-results
fi

40
ci/travis-prepare.sh Normal file
View File

@@ -0,0 +1,40 @@
#!/bin/sh
set -e -x
die() {
echo "$1" >&2
exit 1
}
CURDIR="$PWD"
QDIR="$HOME/.cache/qemu"
if [ -n "$RTEMS" -a "$TEST" = "YES" ]
then
git clone --quiet --branch vme --depth 10 https://github.com/mdavidsaver/qemu.git "$HOME/.build/qemu"
cd "$HOME/.build/qemu"
HEAD=`git log -n1 --pretty=format:%H`
echo "HEAD revision $HEAD"
[ -e "$HOME/.cache/qemu/built" ] && BUILT=`cat "$HOME/.cache/qemu/built"`
echo "Cached revision $BUILT"
if [ "$HEAD" != "$BUILT" ]
then
echo "Building QEMU"
git submodule --quiet update --init
install -d "$HOME/.build/qemu/build"
cd "$HOME/.build/qemu/build"
"$HOME/.build/qemu/configure" --prefix="$HOME/.cache/qemu/usr" --target-list=i386-softmmu --disable-werror
make -j2
make install
echo "$HEAD" > "$HOME/.cache/qemu/built"
fi
fi
cd "$CURDIR"

View File

@@ -20,11 +20,15 @@ else
endif
# Provide a default if the user hasn't set EPICS_HOST_ARCH
ifeq ($(origin EPICS_HOST_ARCH), undefined)
# NB: We use a simply expanded variable here for performance:
EPICS_HOST_ARCH := $(shell $(CONFIG)/../startup/EpicsHostArch.pl)
endif
#
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 :=
endif
-include $(CONFIG)/RELEASE
-include $(CONFIG)/RELEASE.$(EPICS_HOST_ARCH)
@@ -73,17 +77,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 = $(GNU_TARGET:%= $(GNU_DIR)/%/include)
GNU_TARGET_LIB_DIR = $(GNU_TARGET:%= $(GNU_DIR)/%/lib)
GNU_TARGET_INCLUDE_DIR = $(wildcard $(GNU_TARGET:%=$(GNU_DIR)/%/include))
GNU_TARGET_LIB_DIR = $(wildcard $(GNU_TARGET:%=$(GNU_DIR)/%/lib))
CROSS_INCLUDES = $(addprefix -I,$(GNU_TARGET_INCLUDE_DIR))
CROSS_LDFLAGS = $(addprefix -L,$(GNU_TARGET_LIB_DIR))
CROSS_INCLUDES = $(GNU_TARGET_INCLUDE_DIR:%=-I%)
CROSS_LDFLAGS = $(GNU_TARGET_LIB_DIR:%=-L%)
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

@@ -68,6 +68,7 @@ DBTOMENUH = $(PERL) $(TOOLS)/dbdToMenuH.pl
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
#-------------------------------------------------------
# tools for installing libraries and products

View File

@@ -27,7 +27,7 @@ EPICS_VERSION = 3
EPICS_REVISION = 15
# EPICS_MODIFICATION must be a number >=0 and <256
EPICS_MODIFICATION = 5
EPICS_MODIFICATION = 6
# EPICS_PATCH_LEVEL must be a number (win32 resource file requirement)
# Not included if zero

View File

@@ -117,11 +117,10 @@ CROSS_COMPILER_TARGET_ARCHS=
# configure/os/CONFIG_SITE.<host>.Common files instead.
CROSS_COMPILER_HOST_ARCHS=
# The 'make runtests' and 'make tapfiles' build targets normally only run
# The 'runtests', 'tapfiles' and 'junitfiles' make targets normally only run
# self-tests for the EPICS_HOST_ARCH architecture. If the host can execute
# the self-test programs for any other cross-built architectures such as
# a -debug architecture, those architectures can be named here.
#
# a -debug architecture, those architectures must be named in this variable:
CROSS_COMPILER_RUNTEST_ARCHS=
# Build shared libraries (DLLs on Windows).
@@ -175,3 +174,5 @@ GCC_PIPE = NO
# run at build-time, e.g. set the LD_LIBRARY_PATH environment variable.
LINKER_USE_RPATH = YES
# Overrides for the settings above may appear in a CONFIG_SITE.local file
-include $(CONFIG)/CONFIG_SITE.local

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,31 +26,42 @@
# Time service:
# EPICS_TIMEZONE
# 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
# 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.
#
# 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
# (see: http://www.timeanddate.com/time/dst/2016.html etc. )
#EPICS_TIMEZONE = CUS::360:031402:110702
#EPICS_TIMEZONE = MET::-60:032802:103103
#
# These values are for 2016:
EPICS_TIMEZONE=CST/CDT::360:031302:110602
#EPICS_TIMEZONE=CET/CEST::-60:032702:103002
# 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
# EPICS_TS_NTP_INET
# NTP time server ip address. Uses boot host if not set.
# NTP time server ip address for VxWorks and RTEMS.
# IOC will use its boot host if this is not set.
EPICS_TS_NTP_INET=
# IOC Shell:

View File

@@ -1,19 +1,20 @@
#*************************************************************************
# Copyright (c) 2002 The University of Chicago, as Operator of Argonne
# Copyright (c) 2012 UChicago Argonne LLC, as Operator of Argonne
# National Laboratory.
# Copyright (c) 2002 The Regents of the University of California, as
# Operator of Los Alamos National Laboratory.
# EPICS BASE Versions 3.13.7
# and higher are distributed subject to a Software License Agreement found
# in 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.
#*************************************************************************
# RELEASE: Define location of external EPICS products
#
# RELEASE: Define the location of external EPICS products
#
# The version of this file in Base should normally be empty.
#
# Define INSTALL_LOCATION in CONFIG_SITE
# VX_DIR definition now in os/CONFIG_SITE.Common.vxWorksCommon
# RTEMS_BASE (and RTEMS_VERSION) now in os/CONFIG_SITE.Common.RTEMS
# NB: Settings in RELEASE files can be overridden in files named
# RELEASE.$(EPICS_HOST_ARCH).Common
# RELEASE.Common.$(T_A)

View File

@@ -151,7 +151,7 @@ ACTIONS = inc
ACTIONS += build
ACTIONS += install
ACTIONS += buildInstall
ACTIONS += runtests tapfiles
ACTIONS += runtests tapfiles clean-tests test-results junitfiles
actionArchTargets = $(foreach x, $(ACTIONS),\ $(foreach arch,$(BUILD_ARCHS), $(x)$(DIVIDER)$(arch)))

View File

@@ -14,7 +14,7 @@ build$(DIVIDER)$(ARCH) build: buildInstall
install$(DIVIDER)$(ARCH) install: buildInstall
$(ARCH): buildInstall
ifeq ($(filter $(ARCH),$(BUILD_ARCHS)),$(ARCH))
ifeq ($(filter $(ARCH),$(BUILD_ARCHS)),$(strip $(ARCH)))
buildInstall$(DIVIDER)$(ARCH) buildInstall: $(TARGETS)
clean$(DIVIDER)$(ARCH) clean:
@@ -35,4 +35,3 @@ envPaths: $(wildcard $(TOP)/configure/RELEASE*) \
realclean:
$(RM) cdCommands envPaths dllPath.bat relPaths.sh

View File

@@ -14,7 +14,7 @@ ACTIONS = inc
ACTIONS += build
ACTIONS += install
ACTIONS += buildInstall
ACTIONS += runtests tapfiles
ACTIONS += runtests tapfiles clean-tests test-results junitfiles
actionArchTargets = $(foreach action, $(ACTIONS), \
$(addprefix $(action)$(DIVIDER), $(BUILD_ARCHS)))

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.
#*************************************************************************
#
# Rules for making things specified in Makefile
@@ -25,7 +25,6 @@ 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)
#---------------------------------------------------------------
@@ -103,6 +102,7 @@ endif
# Products and Object libraries
#
PRODTARGETS += $(PRODNAME) $(MUNCHNAME) $(CTDT_SRCS) $(CTDT_OBJS) $(NMS)
TESTPRODTARGETS += $(TESTPRODNAME) $(TESTMUNCHNAME)
#---------------------------------------------------------------
# Test specifications and test result files
@@ -115,10 +115,11 @@ endif
ifneq (,$(findstring $(T_A),$(EPICS_HOST_ARCH) $(CROSS_COMPILER_RUNTEST_ARCHS)))
RUNTESTS_ENABLED = YES
TAPFILES += $(TESTSCRIPTS:.t=.tap)
JUNITFILES += $(TAPFILES:.tap=.xml)
endif
#---------------------------------------------------------------
# Libraries
# Libraries
#
LIBTARGETS += $(LIBNAME) $(INSTALL_LIBS) $(TESTLIBNAME) \
@@ -129,18 +130,18 @@ LIBTARGETS += $(LIBNAME) $(INSTALL_LIBS) $(TESTLIBNAME) \
# Main targets
install: buildInstall
install: buildInstall
buildInstall : build
buildInstall: build
# Allows rebuild to work with parallel builds option, -j.
install: $(patsubst rebuild,clean,$(filter rebuild,$(MAKECMDGOALS)))
rebuild: clean install
build : inc
build: inc
build: $(OBJSNAME) $(LIBTARGETS) $(PRODTARGETS) $(TESTPRODNAME) \
build: $(OBJSNAME) $(LIBTARGETS) $(PRODTARGETS) $(TESTPRODTARGETS) \
$(TARGETS) $(TESTSCRIPTS) $(INSTALL_LIB_INSTALLS)
inc : $(COMMON_INC) $(INSTALL_INC) $(INSTALL_CONFIGS)
@@ -158,20 +159,21 @@ clean: build_clean
build_clean:
$(ECHO) "Cleaning"
@$(RM) *.i *$(OBJ) *.a $(TESTPRODNAME) \
@$(RM) *.i *$(OBJ) *.a \
$(LIBNAME) $(TESTLIBNAME) $(SHRLIBNAME) $(TESTSHRLIBNAME) \
$(DLLSTUB_LIBNAME) $(TESTDLLSTUB_LIBNAME) \
$(LOADABLE_SHRLIBNAME) \
$(INC) $(TARGETS) $(TDS) $(CLEANS) \
*.out MakefileInclude *.manifest *.exp \
$(COMMON_INC) $(HDEPENDS_FILES) $(PRODTARGETS) \
$(TESTSCRIPTS) $(TAPFILES)
$(COMMON_INC) $(HDEPENDS_FILES) $(PRODTARGETS) $(TESTPRODTARGETS) \
$(TESTSCRIPTS) $(TAPFILES) $(JUNITFILES)
ifdef RES
@$(RM) *$(RES)
endif
$(DIRECTORY_TARGETS) :
$(MKDIR) -p $@
# Sort mkdir targets to remove duplicates & make parents first
$(DIRECTORY_TARGETS):
$(MKDIR) $(sort $@)
# Install LIB_INSTALLS libraries before linking executables
$(TESTPRODNAME) $(PRODNAME): | $(INSTALL_LIB_INSTALLS)
@@ -188,7 +190,7 @@ warnRelease:
-$(CONVERTRELEASE) checkRelease
noCheckRelease:
ifeq ($(EPICS_HOST_ARCH),$(T_A))
@echo "Warning: RELEASE file consistency checks have been disabled"
$(info Warning: RELEASE file consistency checks have been disabled)
endif
#---------------------------------------------------------------
@@ -254,15 +256,13 @@ YACCOPT ?= $($*_YACCOPT)
$(MV) $*.tab.c $*.c
$(if $(findstring -d, $(YACCOPT)),$(MV) $*.tab.h $*.h,)
# must be a seperate rule since when not using '-d' the
# must be a separate 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) $@
$(MV) $*.yy.c $@
$(LEX) $(LEXOPT) -o$@ $<
#---------------------------------------------------------------
# Libraries, shared/DLL and stubs
@@ -279,13 +279,17 @@ endif # RANLIB
$(SHRLIBNAME) $(DLLSTUB_LIBNAME) $(TESTSHRLIBNAME) $(TESTDLLSTUB_LIBNAME): \
$(LIBRARY_OBJS) $(LIBRARY_RESS) $(SHRLIB_DEPLIBS)
$(DLLSTUB_LIBNAME): $(SHRLIBNAME);
# Stub library timestamps may be earlier than the DLL itself.
# This order-only prerequisite resolves any related problems.
# The $(LINK.shrlib) command must build both library files if
# the target requires a separate stub library file.
$(DLLSTUB_LIBNAME): | $(SHRLIBNAME);
$(SHRLIBNAME): $(SHRLIB_PREFIX)%$(SHRLIB_SUFFIX):
@$(RM) $@
$(LINK.shrlib)
$(MT_DLL_COMMAND)
$(TESTDLLSTUB_LIBNAME): $(TESTSHRLIBNAME);
$(TESTDLLSTUB_LIBNAME): | $(TESTSHRLIBNAME);
$(TESTSHRLIBNAME): $(SHRLIB_PREFIX)%$(SHRLIB_SUFFIX):
@$(RM) $@
$(LINK.shrlib)
@@ -317,6 +321,10 @@ $(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)
@@ -340,7 +348,23 @@ testspec: $(TESTSCRIPTS)
$(if $(TESTFILES), @echo Files: $(TESTFILES) >> $@)
$(if $(TESTSPEC_$(OS_CLASS)), @echo "Harness: $(TESTSPEC_$(OS_CLASS))" >> $@)
test-results: tapfiles
ifneq ($(TAPFILES),)
ifdef RUNTESTS_ENABLED
prove --failures --ext .tap --exec "$(CAT)" --color $(TAPFILES)
endif
endif
clean-tests:
ifneq ($(TAPFILES),)
$(RM) $(TAPFILES)
endif
ifneq ($(JUNITFILES),)
$(RM) $(JUNITFILES)
endif
tapfiles: $(TESTSCRIPTS) $(TAPFILES)
junitfiles: $(JUNITFILES)
# A .tap file is the output from running the associated test script
%.tap: %.t
@@ -348,6 +372,9 @@ ifdef RUNTESTS_ENABLED
-$(PERL) $< -tap > $@
endif
%.xml: %.tap
$(TAPTOJUNIT) --puretap --output $@ --input $< $*
# If there's a perl test script (.plt) available, use it
%.t: ../%.plt
@$(RM) $@
@@ -492,7 +519,8 @@ $(INSTALL_TEMPLATES_SUBDIR)/%: %
.PRECIOUS: $(COMMON_INC)
.PHONY: all host inc build install clean rebuild buildInstall build_clean
.PHONY: runtests tapfiles checkRelease warnRelease noCheckRelease
.PHONY: runtests tapfiles clean-tests test-results junitfiles
.PHONY: checkRelease warnRelease noCheckRelease
endif # BASE_RULES_BUILD
# EOF RULES_BUILD

View File

@@ -9,7 +9,7 @@
ARCHS += $(BUILD_ARCHS)
ACTIONS += inc build install buildInstall clean realclean archclean
ACTIONS += runtests tapfiles
ACTIONS += runtests tapfiles clean-tests test-results junitfiles
dirActionArchTargets = $(foreach dir, $(DIRS), \
$(foreach action, $(ACTIONS), \

View File

@@ -38,6 +38,17 @@ $(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))), \
@@ -123,16 +134,6 @@ $(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

@@ -57,6 +57,7 @@ help:
@echo " Cannot be used within an O.<arch> dir"
@echo " rebuild - Same as clean install"
@echo " archclean - Removes O.<arch> dirs but not O.Common dir"
@echo " runtests - Run self-tests, summarize results"
@echo "\"Partial\" build targets supported by Makefiles:"
@echo " host - Builds and installs $(EPICS_HOST_ARCH) only."
@echo " inc$(DIVIDER)<arch> - Installs <arch> only header files."

View File

@@ -136,6 +136,13 @@ 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,7 +15,6 @@ 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,7 +13,6 @@ 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,7 +7,6 @@ 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,7 +15,6 @@ 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,7 +16,6 @@ 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,7 +8,6 @@
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,7 +9,6 @@ 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,5 +15,14 @@ ARCH_CLASS = xscale
ifeq ($(BUILD_CLASS),CROSS)
VALID_BUILDS = Ioc
GNU_TARGET = xscale_be
CMPLR_PREFIX = $(addsuffix -,$(GNU_TARGET))
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)
endif

View File

@@ -23,13 +23,15 @@ STATIC_LDFLAGS_YES= -Wl,-Bstatic
STATIC_LDFLAGS_NO=
STATIC_LDLIBS_YES= -Wl,-Bdynamic
# 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 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 products
PRODDIR_RPATH_LDFLAGS_YES += $(PROD_DEPLIB_DIRS:%=-Wl,-rpath,%)
PRODDIR_LDFLAGS += $(PRODDIR_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))
# Link libraries controlled by COMMANDLINE_LIBRARY
# The newest Linux versions only need readline, older ones need both

View File

@@ -106,20 +106,10 @@ GNU_DIR_6 = $(WIND_BASE)/gnu/$(VX_GNU_VERSION)-vxworks-$(VXWORKS_VERSION)/$(WIND
GNU_DIR = $(GNU_DIR_$(VXWORKS_MAJOR_VERSION))
#--------------------------------------------------
# Wind River moved nm out of GNU_BIN in some versions
# This finds nm on any supported VxWorks version
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)
NMPROG = $(CMPLR_PREFIX)nm$(CMPLR_SUFFIX)$(HOSTEXE)
NM = $(firstword $(wildcard $(WIND_BASE)/*/$(WIND_HOST_TYPE)/bin/$(NMPROG)))
#--------------------------------------------------
# A linker script is essential for munching from vxWorks 6.6 onwards
@@ -132,6 +122,7 @@ 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
@@ -179,6 +170,8 @@ 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

@@ -65,14 +65,14 @@ GNU = NO
#
# Darwin shared libraries
#
SHRLIB_LDFLAGS = -dynamiclib -flat_namespace -undefined suppress \
SHRLIB_LDFLAGS = -dynamiclib -undefined dynamic_lookup \
-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 -flat_namespace -undefined suppress
LOADABLE_SHRLIB_LDFLAGS = -bundle -undefined dynamic_lookup
#
# Position-independent code is the default on Darwin.

View File

@@ -11,19 +11,14 @@ GNU_TARGET = arm-linux
CMPLR_SUFFIX =
CMPLR_PREFIX = $(addsuffix -,$(GNU_TARGET))
# 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))
# 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)
# Library flags
STATIC_LDFLAGS_YES= -Wl,-Bstatic

View File

@@ -79,27 +79,32 @@ 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
CODE_CPPFLAGS += -nologo -D__STDC__=0
# 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 += -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE
# Compiler flags for C++ files
#
# -W<N> use warning level N
# (maximum lint level warnings at level 4)
# -w44355 set "'this' used in the base initializer list" to be level 4
# -W<n> disable warnings from levels > n
# -w<n><m> set warning m to level n
# -w44355 "'this' used in the base initializer list"
# -w44344 "behavior change: use of explicit template arguments results in ..."
WARN_CXXFLAGS_YES = -W3 -w44355 -w44344
# -w44251 "class needs to have dll-interface to be used by clients of ..."
WARN_CXXFLAGS_YES = -W3 -w44355 -w44344 -w44251
WARN_CXXFLAGS_NO = -W1
#
@@ -135,6 +140,16 @@ 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
@@ -165,48 +180,38 @@ EXE=.exe
OBJ=.obj
RES=.res
# Problem: MS Visual C++ does not recognize *.cc as C++ source,
# so we do C++ compiles using the global flag -TP
# MS Visual C++ doesn't recognize *.cc as a C++ source file,
# so C++ compiles get the flag -TP
COMPILER_CXXFLAGS = -TP
# Operating system flags
# Operating system flags
OP_SYS_CFLAGS =
OP_SYS_CXXFLAGS = $(COMPILER_CXXFLAGS)
#
# Files and flags needed to link DLLs (used in RULES_BUILD)
#
WIN32_DLLFLAGS = /subsystem:windows /dll $(OPT_LDFLAGS) \
# Files and flags needed to link DLLs (used in RULES_BUILD)
WIN32_DLLFLAGS = -subsystem:windows -dll $(OPT_LDFLAGS) \
$(USR_LDFLAGS) $(CMD_LDFLAGS) $(TARGET_LDFLAGS) $(LIB_LDFLAGS)
#
# specify dll .def file only if it exists
#
# Specify dll .def file only if it exists
DLL_DEF_FLAG = $(addprefix -def:,$(wildcard ../$(addsuffix .def,$*)))
#
# A WIN32 dll has three parts:
# A WIN32 dll has three parts:
# x.dll: the real dll (SHRLIBNAME)
# x.lib: what you link to progs that use the dll (DLLSTUB_LIBNAME)
# x.exp: what you need to build the dll (in no variable)
#
LINK.shrlib = $(WINLINK) -nologo $(WIN32_DLLFLAGS) -out:$@ \
-implib:$(@:%$(SHRLIB_SUFFIX)=%$(LIB_SUFFIX)) \
$(DLL_DEF_FLAG) $(LIBRARY_LD_OBJS) $(LIBRARY_LD_RESS) $(SHRLIB_LDLIBS)
# adjust names of libraries to build
#
# Adjust names of libraries to build
SHRLIB_SUFFIX_BASE = .dll
SHRLIB_SUFFIX = $(SHRLIB_SUFFIX_BASE)
SHRLIBNAME_YES = $(BUILD_LIBRARY:%=%$(SHRLIB_SUFFIX))
LOADABLE_SHRLIBNAME = $(LOADABLE_BUILD_LIBRARY:%=%$(SHRLIB_SUFFIX))
TESTSHRLIBNAME_YES = $(TESTBUILD_LIBRARY:%=%$(SHRLIB_SUFFIX_BASE))
#
# When SHARED_LIBRARIES is YES we are building a DLL link library
# and when SHARED_LIBRARIES is NO we are building an object library
#
# When SHARED_LIBRARIES is YES we are building a DLL shared library.
# When SHARED_LIBRARIES is NO we are building an object library
DLLSTUB_SUFFIX = .lib
DLLSTUB_LIBNAME_YES = $(BUILD_LIBRARY:%=%.lib)
DLLSTUB_LIBNAME = $(DLLSTUB_LIBNAME_$(SHARED_LIBRARIES))
@@ -220,7 +225,7 @@ LIBNAME = $(LIBNAME_$(SHARED_LIBRARIES))
TESTLIBNAME_NO = $(TESTBUILD_LIBRARY:%=%.lib)
TESTLIBNAME = $(TESTLIBNAME_$(SHARED_LIBRARIES))
# dll install location
# dll install location
INSTALL_SHRLIB = $(INSTALL_BIN)
@@ -280,7 +285,7 @@ LINK.cpp = $(WINLINK) -nologo $(STATIC_LDFLAGS) $(LDFLAGS) $(PROD_LDFLAGS) \
#--------------------------------------------------
# UseManifestTool.pl checks MS Visual c++ compiler version number to
# decide whether or not to use the Manifest Tool command to embed the
# linker created .manifest file into a library or product target.
# linker created .manifest file into a library or product target.
# useManifestTool.pl returns 0(don't use) or 1(use).
#
MT.exe = mt.exe -nologo -manifest $@.manifest
@@ -290,4 +295,3 @@ MT_EXE_COMMAND_NO = $(MT.exe) "-outputresource:$@;\#1"
MT_EXE_COMMAND1 = $(MT_EXE_COMMAND_$(STATIC_BUILD))
MT_DLL_COMMAND = $(MT_DLL_COMMAND$(shell $(PERL) $(TOOLS)/useManifestTool.pl))
MT_EXE_COMMAND = $(MT_EXE_COMMAND$(shell $(PERL) $(TOOLS)/useManifestTool.pl))

View File

@@ -8,8 +8,7 @@
include $(CONFIG)/os/CONFIG.win32-x86.win32-x86
-include $(CONFIG)/os/CONFIG_SITE.win32-x86.win32-x86
OPT_LDFLAGS += /MACHINE:X64
# /MACHINE:X64
# /MACHINE:IA64 (Itanium)
# /MACHINE:X86
OPT_LDFLAGS += -MACHINE:X64
# -MACHINE:X64
# -MACHINE:IA64 (Itanium)
# -MACHINE:X86

View File

@@ -1,10 +1,4 @@
# CONFIG_SITE.Common.linux-xscale_be
#
# Site specific definitions for linux-xscale_be target builds.
# Site specific definitions for all 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

@@ -9,7 +9,7 @@
# Note: vxWorks 5.4.x (Tornado 2.0.x) is not supported
VXWORKS_VERSION = 5.5
#VXWORKS_VERSION = 5.5
#VXWORKS_VERSION = 6.0
#VXWORKS_VERSION = 6.1
#VXWORKS_VERSION = 6.2
@@ -19,7 +19,7 @@ VXWORKS_VERSION = 5.5
#VXWORKS_VERSION = 6.6
#VXWORKS_VERSION = 6.7
#VXWORKS_VERSION = 6.8
#VXWORKS_VERSION = 6.9
VXWORKS_VERSION = 6.9
# Sites may override the following path for a particular host
@@ -29,19 +29,6 @@ VXWORKS_VERSION = 5.5
# 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 = /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,8 +7,25 @@
GNU_TARGET = arm-xilinx-linux-gnueabi
# Set GNU tools install path
# This is the install path at APS:
# Examples are installations at the 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

@@ -0,0 +1,11 @@
# 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

@@ -0,0 +1,7 @@
# 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,18 +4,18 @@
<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.5</title>
<title>Known Problems in R3.15.6</title>
</head>
<body>
<h1 style="text-align: center">EPICS Base R3.15.5: Known Problems</h1>
<h1 style="text-align: center">EPICS Base R3.15.6: Known Problems</h1>
<p>Any patch files linked below should be applied at the root of the
base-3.15.5 tree. Download them, then use the GNU Patch program as
base-3.15.6 tree. Download them, then use the GNU Patch program as
follows:</p>
<blockquote><pre>% <b>cd <i>/path/to/</i>base-3.15.5</b>
% <b>patch -p0 &lt; <i>/path/to/</i>file.patch</b></pre></blockquote>
<blockquote><pre>% <b>cd <i>/path/to/</i>base-3.15.6</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>

View File

@@ -1,24 +1,24 @@
Installation Instructions
EPICS Base Release 3.15.5
EPICS Base Release 3.15.6
--------------------------------------------------------------------------
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
--------------------------------------------------------------------------
@@ -166,12 +166,11 @@
base/startup directory - contains scripts to set environment and path
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
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
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/Site.profile
<strong>.</strong> "${EPICS_BASE}"/startup/unix.sh
</pre>
</li>
<li>

View File

@@ -9,7 +9,7 @@
<BODY>
<CENTER>
<H1>Installation Instructions</H1>
<H2>EPICS Base Release 3.15.5</H2><BR>
<H2>EPICS Base Release 3.15.6</H2><BR>
</CENTER>
<HR>
<H3> Table of Contents</H3>
@@ -98,8 +98,8 @@
base/configure/os/CONFIG_SITE.Common.vxWorksCommon file or in one of its
target-specific overrides.</P>
<P>Consult the <a href="http://www.aps.anl.gov/epics/base/tornado.php">vxWorks
5.x</a> or <a href="http://www.aps.anl.gov/epics/base/vxWorks6.php">vxWorks
<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
about configuring your vxWorks operating system for use with EPICS.</P>
@@ -129,7 +129,7 @@
<H3><A NAME="0_0_8"> Documentation</A></H3>
<BLOCKQUOTE>EPICS documentation is available through the
<a href="http://www.aps.anl.gov/epics/">EPICS website</a> at Argonne.
<a href="https://epics.anl.gov/">EPICS website</a> at Argonne.
<P>Release specific documentation can also be found in the base/documentation
directory of the distribution.</BLOCKQUOTE>
@@ -177,12 +177,11 @@
<H4>base/startup directory - contains scripts to set environment and path</H4>
<PRE>
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
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
</PRE>
<H4>base/configure directory - contains build definitions and rules</H4>

View File

@@ -3,18 +3,262 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<title>EPICS Base R3.15.5 Release Notes</title>
<title>EPICS Base R3.15.6 Release Notes</title>
</head>
<body lang="en">
<h1 align="center">EPICS Base Release 3.15.5</h1>
<h1 align="center">EPICS Base Release 3.15.6</h1>
<p style="color:red">This version of EPICS Base has not been released yet.</p>
<h2 align="center">Changes made on the 3.15 branch since 3.15.4</h2>
<h2 align="center">Changes made on the 3.15 branch since 3.15.5</h2>
<!-- Insert new items immediately below here ... -->
<h3>Warning indicators in msi (and macLib) output</h3>
<p>The libCom macro expansion library has been modified so that when the
SUPPRESS_WARNINGS flag is set it will no longer include any <tt>,undefined</tt>
or <tt>,recursive</tt> indicators in its output when undefined or recursive
macros are encountered. These indicators were harmless when the output was fed
into an IOC along with a definition for the macro, but when the <tt>msi</tt>
tool was used to generate other kinds of files they caused problems. If the
<tt>msi -V</tt> flag is used the markers will still be present in the output
whenever the appropriate condition is seen.</p>
<h3>Improvements to msi</h3>
<p>In addition to fixing its response to discovering parsing errors in its
substitution input file (reported as Launchpad
<a href="https://bugs.launchpad.net/epics-base/+bug/1503661">bug #1503661</a>)
so it now deletes the incomplete output file, the msi program has been cleaned
up a little bit internally.</p>
<h3>All array records now post monitors on their array-length fields</h3>
<p>The waveform record has been posting monitors on its NORD field since Base
3.15.0.1; we finally got around to doing the equivalent in all the other
built-in record types, which even required modifying device support in some
cases. This fixes <a href="https://bugs.launchpad.net/epics-base/+bug/1730727">
Launchpad bug #1730727</a>.</p>
<h3>HOWTO: Converting Wiki Record Reference to POD</h3>
<p>Some documentation has been added to the <tt>dbdToHtml.pl</tt> script
explaining how Perl POD (Plain Old Documentation) markup can be added to
<tt>.dbd</tt> files to generate HTML documentation for the record types. To see
these instructions, run <tt>perl&nbsp;bin/&lt;host&gt;/dbdToHtml.pl&nbsp;-H</tt>
or <tt>perldoc&nbsp;bin/&lt;host&gt;/dbdToHtml.pl</tt>.</p>
<h3>Fix problem with numeric soft events</h3>
<p>Changing from numeric to named soft events introduced an incompatibility
when a numeric event 1-255 is converted from a DOUBLE, e.g. from a calc record.
The <tt>post_event()</tt> API is not marked deprecated any more.
<p>Also <code>scanpel</code> has been modified to accept a glob pattern for
event name filtering and to show events with no connected records as well.</p>
<h3>Add osiSockOptMcastLoop_t and osiSockTest</h3>
<p>Added a new OS-independent typedef for multicast socket options, and a test
file to check their correct operation.<p>
<h3>Support for CONFIG_SITE.local in Base</h3>
<p>This feature is mostly meant for use by developers; configuration
settings that would normally appear in Base/configure/CONFIG_SITE can now
be put in a locally created base/configure/CONFIG_SITE.local file instead
of having go modify or replace the original. A new .gitignore pattern
tells git to ignore all configure/*.local files.</p>
<h2 align="center">Changes from the 3.14 branch since 3.15.5</h2>
<!-- Insert inherited items immediately below here ... -->
<h3>Fix broken <tt>EPICS_IOC_LOG_FILE_LIMIT=0</tt> setting</h3>
<p>The Application Developers' Guide says this is allowed and disables the
limit on the log-file, but it hasn't actually worked for some time (if ever).
Note that the iocLogServer will be removed from newer Base release sometime
soon as its functionality can be implemented by other dedicated log servers
such as logstash or syslog-ng.</p>
<p>Fixes <a href="https://bugs.launchpad.net/bugs/1786858">lp:1786858</a>
and part of <a href="https://bugs.launchpad.net/bugs/1786966">lp:1786966</a>.
</p>
<h3>Cleanup of startup directory</h3>
<p>The files in the startup directory have not been maintained in recent years
and have grown crufty (technical term). This release includes the following
updates to these files:</p>
<ul>
<li>The Perl <tt>EpicsHostArch.pl</tt> script has been rewritten, and support
for a few previously missing host architectures has been added to it.</li>
<li>The <tt>EpicsHostArch.pl</tt> script has also been moved into the standard
<tt>src/tools</tt> directory, from where it will be installed into
<tt>lib/perl</tt>. In this new location it is no longer executable, so it must
be run by the <tt>perl</tt> executable.</li>
<li>The build system has been adjusted to look for <tt>EpicsHostArch.pl</tt> in
both places if the <tt>EPICS_HOST_ARCH</tt> environment variable has not been
set at build-time.</li>
<li>Sites that used the original Perl script to set <tt>EPICS_HOST_ARCH</tt> as
part of their standard environment will need to adjust their scripts when they
upgrade to this release.</li>
<li>The <tt>EpicsHostArch</tt> shell script has been replaced with a wrapper
routine that calls the Perl <tt>EpicsHostArch.pl</tt> script. Sites that rely on
this script to set <tt>EPICS_HOST_ARCH</tt> should consider switching to the
Perl script instead.</li>
<li>The <tt>Site.cshrc</tt> and <tt>Site.profile</tt> files have been renamed to
<tt>unix.csh</tt> and <tt>unix.sh</tt>, respectively.</li>
<li>The existing <tt>win32.bat</tt> file has been cleaned up and a new
<tt>windows.bat</tt> file added for 64-bit targets. The contents of these files
should be seen as examples, don't uncomment or install parts for software that
you don't explicitly know that you need.</li>
</ul>
<h3>Recent Apple XCode Build Issues</h3>
<p>The latest version of XCode will not compile calls to <tt>system()</tt> or
<tt>clock_settime()</tt> for iOS targets. There were several places in Base
where these were being compiled, although there were probably never called. The
code has now been modified to permit iOS builds to complete again.</p>
<h3>Prevent illegal alarm severities</h3>
<p>A check has been added to <tt>recGblResetAlarms()</tt> that prevents records
from getting an alarm severity higher than INVALID_ALARM. It is still possible
for a field like HSV to get set to a value that is not a legal alarm severity,
but the core IOC code should never copy such a value into a record's SEVR or
ACKS fields. With this fix the record's alarm severity will be limited to
INVALID_ALARM.</p>
<h3>Fixes for Launchpad bugs</h3>
<p>The following launchpad bugs have fixes included:</p>
<ul>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1786320">
lp: #1786320</a>, dbCa subscribes twice to ENUM</li>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/541221">
lp: #541221</a>, 'assert (pca->pgetNative)' failed in ../dbCa.c</li>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1747091">
lp: #1747091</a>, epicsTimeGetEvent() / generalTime bug</li>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1743076">
lp: #1743076</a>, Segfault in ca_attach_context() during exits</li>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1751380">
lp: #1751380</a>, Deadlock in ca_clear_subscription()</li>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1597809">
lp: #1597809</a>, Setting NAME field in DB file may break IOC</li>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1770292">
lp: #1770292</a>, get_alarm_double() inconsistent across record types</li>
<li><a href="https://bugs.launchpad.net/epics-base/+bug/1771298">
lp: #1771298</a>, Conversion of NaN to integer relies on undefined
behavior</li>
</ul>
<h3>Updated VxWorks Timezone settings</h3>
<p>Removed the settings for 2017; fixed the hour of the change for MET.</p>
<h3>Fixed camonitor server side relative timestamps bug</h3>
<p>Initialize the first time-stamp from the first monitor, not the client-side
current time in this configuration.</p>
<h3>Build changes for MSVC</h3>
<p>Windows builds using Visual Studio 2015 and later now use the <tt>-FS</tt>
compiler option to allow parallel builds to work properly.</p>
<p>We now give the <tt>-FC</tt> option to tell the compiler to print absolute
paths for source files in diagnostic messages.</p>
<h3>Extend maximum Posix epicsEventWaitWithTimeout() delay</h3>
<p>The Posix implementation of epicsEventWaitWithTimeout() was limiting the
timeout delay to at most 60 minutes (3600.0 seconds). This has been changed to
10 years; significantly longer maximum delays cause problems on systems where
<tt>time_t</tt> is still a signed 32-bit integer so cannot represent absolute
time-stamps after 2038-01-19. Our assumption is that such 32-bit systems will
have been retired before the year 2028, but some additional tests have been
added to the epicsTimeTest program to detect and fail if this assumption is
violated.</p>
<h3>New test-related make targets</h3>
<p>This release adds several new make targets intended for use by developers
and Continuous Integration systems which simplify the task of running the
built-in self-test programs and viewing the results. Since these targets are
intended for limited use they can have requirements for the build host which
go beyond the standard minimum set needed to build and run Base.</p>
<blockquote>
<h4><tt>test-results</tt> &mdash; Summarize test results</h4>
<p>The new make target <tt>test-results</tt> will run the self-tests if
necessary to generate a TAP file for each test, then summarizes the TAP output
files in each test directory in turn, displaying the details of any failures.
This step uses the program <q>prove</q> which comes with Perl, but also needs
<q>cat</q> to be provided in the default search path so will not work on most
Windows systems.</p>
<h4><tt>junitfiles</tt> &mdash; Convert test results to JUnit XML Format</h4>
<p>The new make target <tt>junitfiles</tt> will run the self-tests if necessary
and then convert the TAP output files into the more commonly-supported JUnit
XML format. The program that performs this conversion needs the Perl module
<q><tt>XML::Generator</tt></q> to have been installed.</p>
<h4><tt>clean-tests</tt> &mdash; Delete test result files</h4>
<p>The new make target <tt>clean-tests</tt> removes any test result files from
previous test runs. It cleans both TAP and JUnit XML files.</p>
</blockquote>
<h3>Fix DNS related crash on exit</h3>
<p>The attempt to fix DNS related delays for short lived CLI programs (eg. caget)
in lp:1527636 introduced a bug which cased these short lived clients to crash on exit.
This bug should now be fixed.</p>
<h3>Server bind issue on Windows</h3>
<p>When a National Instruments network variables CA server is already running on
a Windows system and an IOC or PCAS server is started, the IOC's attempt to
bind a TCP socket to the CA server port number fails, but Windows returns a
different error status value than the IOC is expecting in that circumstance
(because the National Instruments code requests exclusive use of that port,
unlike the EPICS code) so the IOC fails to start properly. The relevent EPICS
bind() checks have now been updated so the IOC will request that a dynamic port
number be allocated for this TCP socket instead when this happens.</p>
<h3>Checking Periodic Scan Rates</h3>
<p>Code has been added to the IOC startup to better protect it against bad
periodic scan rates, including against locales where <q><tt>.</tt></q> is not
accepted as a decimal separator character. If the scan period in a menuScan
choice string cannot be parsed, the associated periodic scan thread will no
longer be started by the IOC and a warning message will be displayed at iocInit
time. The <tt>scanppl</tt> command will also flag the faulty menuScan value.</p>
<h2 align="center">Changes made between 3.15.4 and 3.15.5</h2>
<h3>dbStatic Library Speedup and Cleanup</h3>
<p>Loading of database files has been optimized to avoid overproportionally
@@ -28,10 +272,6 @@ old behavior.</p>
to be used by database configuration tools linked against a host side version
of the dbStatic library that is not being built anymore.</p>
<h2 align="center">Changes from the 3.14 branch since 3.15.4</h2>
<!-- Insert inherited items immediately below here ... -->
<h3>Launchpad Bug-fixes</h3>
<p>In addition to the more detailed change descriptions below, the following
@@ -1519,7 +1759,7 @@ The iocLogServer was moved into the same directory (src/libCom/log) as
the log client code.</p>
<p><a name="as">3</a>
The Access Security code has been divided, with the parts not related to the
The Access Security code has been divided, with the parts not related to the
database (lexer/parser and trap registration) becoming part of libCom.
The remaining components are included in the dbCore library</p>

View File

@@ -41,11 +41,12 @@ that should be performed when creating new releases of EPICS Base.</p>
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 about weekly intervals during the testing and debugging period, and
will be designated as either pre-release versions or Release Candidates by the
Release Manager. A Release Candidate that has received widespread testing for a
week without any additional problems being discovered or significant changes
being committed can be designated as the final release version.</p>
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
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>
@@ -56,7 +57,7 @@ relevent roles unless the Release Manager designates otherwise:</p>
<dl>
<dt><strong>Release Manager</strong> (Ralph Lange)</dt>
<dd>Responsible for managing and tagging the release</dd>
<dt><strong>Platform Developers</strong></dt>
<dt><strong>Platform Developers</strong> (optional)</dt>
<dd>Responsible for individual operating system platforms</dd>
<dt><strong>Application Developers</strong></dt>
<dd>Responsible for support modules that depend on EPICS Base.</dd>
@@ -90,7 +91,7 @@ relevent roles unless the Release Manager designates otherwise:</p>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Set the Feature Freeze date, by which time all Bazaar commits for
<td>Set the Feature Freeze date, by which time all Git commits for
enhancements and new functionality should have been completed. After
this date, commits should only be made to fix problems that show up
during testing.</td>
@@ -132,39 +133,36 @@ relevent roles unless the Release Manager designates otherwise:</p>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Tag the module in Bazaar, using these tag conventions:
<td>Tag the module in Git, using these tag conventions:
<ul>
<li>
<tt>R3.15.5-pre<i>n</i></tt>
<tt>R3.15.6-pre1</tt>
&mdash; pre-release tag
</li>
<li>
<tt>R3.15.5-rc<i>n</i></tt>
&mdash; release candidate tag, note the <tt>rc</tt> is now
lower-case</li>
<tt>R3.15.6-rc1</tt>
&mdash; release candidate tag
</li>
</ul>
<blockquote><tt>
cd ~/base/mirror-3.15<br />
bzr tag R3.15.5-rc<i>n</i>
cd base-3.15<br />
git tag -m 'RL: Tagged for 3.15.6-rc1' R3.15.6-rc1
</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. 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:
<blockquote><tt>
cd ~/base<br />
bzr export
--root=base-3.15.5-rc<i>n</i>
-r tag:R3.15.5-rc<i>n</i>
base-3.15.5-rc<i>n</i>.tar.gz
mirror-3.15
cd base-3.15<br />
git archive --prefix=base-3.15.6-rc1/ R3.15.6-rc1 --output=base-3.15.6-rc1.tar.gz
</tt></blockquote>
Create a GPG signature file of the tarfile as follows:
<blockquote><tt>
gpg --armor --sign --detach-sig base-3.15.5-rc<i>n</i>.tar.gz
gpg --armor --sign --detach-sig base-3.15.6-rc1.tar.gz
</tt></blockquote>
</td>
</tr>
@@ -273,10 +271,10 @@ relevent roles unless the Release Manager designates otherwise:</p>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Tag the module in Bazaar:
<td>Tag the module in Git:
<blockquote><tt>
cd ~/base/mirror-3.15<br />
bzr tag R3.15.5</i>
cd base-3.15<br />
git tag -m 'RL: Tagged for 3.15.6' R3.15.6
</tt></blockquote>
</td>
</tr>
@@ -286,16 +284,12 @@ relevent roles unless the Release Manager designates otherwise:</p>
<td>Export the tagged version into a tarfile. Note that this command
generates a gzipped tarfile directly from the repository:
<blockquote><tt>
cd ~/base<br />
bzr export
--root=base-3.15.5
-r tag:R3.15.5
base-3.15.5.tar.gz
mirror-3.15
cd base-3.15<br />
git archive --prefix=base-3.15.6/ R3.15.6 --output=base-3.15.6.tar.gz
</tt></blockquote>
Create a GPG signature file of the tarfile as follows:
<blockquote><tt>
gpg --armor --sign --detach-sig base-3.15.5.tar.gz
gpg --armor --sign --detach-sig base-3.15.6.tar.gz
</tt></blockquote>
</td>
</tr>
@@ -305,14 +299,24 @@ relevent roles unless the Release Manager designates otherwise:</p>
<td>Test the tar file by extracting its contents and building it on at
least one supported platform</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Upload the release tar file to the Launchpad download area.</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Find all Launchpad bug reports with the status Fix Committed which
have been fixed in this release and mark them Fix Released.</td>
</tr>
<tr>
<th colspan="3">Publish and Announce it</th>
</tr>
<tr>
<td>&nbsp;</td>
<td>Website Manager</td>
<td>If necessary recreate the tarfile following the instructions above.
Copy the tar file and its <tt>.asc</tt> signature file to the Base
<td>Copy the tar file and its <tt>.asc</tt> signature file to the Base
download area of the website.</td>
</tr>
<tr>
@@ -343,24 +347,13 @@ relevent roles unless the Release Manager designates otherwise:</p>
<tr>
<td>&nbsp;</td>
<td>Website Manager</td>
<td>Upload the release tar file to the Launchpad download area.</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Website Manager</td>
<td>Find all Launchpad bug reports with the status Fix Committed which
have been fixed in this release and mark them Fix Released.</td>
<td>Add an entry to the website News page, linking to the new version
webpage.</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Release Manager</td>
<td>Email tech-talk</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Website Manager</td>
<td>Add an entry to the website News page, linking to the new version
webpage.</td>
<td>Announce the release on the tech-talk mailing list.</td>
</tr>
</tbody>
</table>

View File

@@ -1009,7 +1009,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>
@@ -1146,16 +1146,10 @@ the output.</p>
<td>Wide mode "name timestamp value stat sevr" (read PVs as
DBR_TIME_xxx)</td>
</tr>
<tr>
<td>-n</td>
<td>Print DBF_ENUM values as number (default are enum strings)</td>
</tr>
<tr>
<td>-d &lt;type&gt;</td>
<td>Request specific dbr type; use string (DBR_ prefix may be omitted)
<p>or number of one of the following types:</p>
<td>Request specific dbr type; use string (DBR_ prefix may be omitted)<br>
or number of one of the following types:<br>
<table border="1">
<tbody>
<tr>
@@ -1272,6 +1266,14 @@ the output.</p>
</table>
</td>
</tr>
<tr>
<td></td>
<td><strong>Enum format:</strong></td>
</tr>
<tr>
<td>-n</td>
<td>Print DBF_ENUM value as number (default is enum string)</td>
</tr>
<tr>
<td></td>
<td><strong>Arrays:</strong></td>
@@ -1303,15 +1305,15 @@ the output.</p>
</tr>
<tr>
<td>-e &lt;nr&gt;</td>
<td>Use %e format, with &lt;nr&gt; digits after the decimal point</td>
<td>Use %e format, with a precision of &lt;nr&gt; digits</td>
</tr>
<tr>
<td>-f &lt;nr&gt;</td>
<td>Use %f format, with &lt;nr&gt; digits after the decimal point</td>
<td>Use %f format, with a precision of &lt;nr&gt; digits</td>
</tr>
<tr>
<td>-g &lt;nr&gt;</td>
<td>Use %g format, with &lt;nr&gt; digits after the decimal point</td>
<td>Use %g format, with a precision of &lt;nr&gt; digits</td>
</tr>
<tr>
<td>-s</td>
@@ -1349,6 +1351,14 @@ the output.</p>
<td>-0b</td>
<td>Print as binary number</td>
</tr>
<tr>
<td></td>
<td><strong>Alternate output field separator:</strong></td>
</tr>
<tr>
<td>-F &lt;ofs&gt;</td>
<td>Use &lt;ofs&gt; as an alternate output field separator</td>
</tr>
</tbody>
</table>
@@ -1381,9 +1391,10 @@ the output.</p>
<td>Wait time, specifies longer CA timeout, default is 1.0 second</td>
</tr>
<tr>
<td>-m &lt;mask&gt;</td>
<td>Specify CA event mask to use, with &lt;mask&gt; being any combination
of 'v' (value), 'a' (alarm), 'l' (log), 'p' (property). Default: va</td>
<td>-m &lt;msk&gt;</td>
<td>Specify CA event mask to use. &lt;msk&gt; is any combination of<br>
'v' (value), 'a' (alarm), 'l' (log/archive), 'p' (property).<br>
Default event mask is 'va'</td>
</tr>
<tr>
<td>-p &lt;prio&gt;</td>
@@ -1405,8 +1416,8 @@ the output.</p>
'n' = no timestamps<br>
'r' = relative timestamps (time elapsed since start of program)<br>
'i' = incremental timestamps (time elapsed since last update)<br>
'I' = incremental timestamps (time elapsed since last update, by
channel)</td>
'I' = incremental timestamps (time since last update, by channel)<br>
'r', 'i' or 'I' require 's' or 'c' to select the time source</td>
</tr>
<tr>
<td></td>
@@ -1414,7 +1425,7 @@ the output.</p>
</tr>
<tr>
<td>-n</td>
<td>Print DBF_ENUM values as number (default are enum strings)</td>
<td>Print DBF_ENUM values as number (default is enum string)</td>
</tr>
<tr>
<td></td>
@@ -1422,16 +1433,15 @@ the output.</p>
</tr>
<tr>
<td></td>
<td>Value format: Print number of requested values, then list of
values</td>
<td>Array values: Print number of elements, then list of values</td>
</tr>
<tr>
<td>Default:</td>
<td>Print all values</td>
<td>Default: Request and print all elements (dynamic arrays supported)</td>
</tr>
<tr>
<td>-# &lt;count&gt;</td>
<td>Print first &lt;count&gt; elements of an array</td>
<td>-# &lt;num&gt;</td>
<td>Request and print up to &lt;num&gt; elements</td>
</tr>
<tr>
<td>-S</td>
@@ -1439,23 +1449,23 @@ the output.</p>
</tr>
<tr>
<td></td>
<td><strong>Floating point type format:</strong></td>
<td><strong>Floating point format:</strong></td>
</tr>
<tr>
<td>Default:</td>
<td>Use %g format</td>
</tr>
<tr>
<td>-e &lt;nr&gt;</td>
<td>Use %e format, with &lt;nr&gt; digits after the decimal point</td>
<td>-e &lt;num&gt;</td>
<td>Use %e format, with a precision of &lt;num&gt; digits</td>
</tr>
<tr>
<td>-f &lt;nr&gt;</td>
<td>Use %f format, with &lt;nr&gt; digits after the decimal point</td>
<td>-f &lt;num&gt;</td>
<td>Use %f format, with a precision of &lt;num&gt; digits</td>
</tr>
<tr>
<td>-g &lt;nr&gt;</td>
<td>Use %g format, with &lt;nr&gt; digits after the decimal point</td>
<td>-g &lt;num&gt;</td>
<td>Use %g format, with a precision of &lt;num&gt; digits</td>
</tr>
<tr>
<td>-s</td>
@@ -1497,21 +1507,27 @@ the output.</p>
</table>
<h3><a name="caput">caput</a></h3>
<pre>caput [options] &lt;PV name&gt; &lt;value&gt;
<pre>caput [options] &lt;PV name&gt; &lt;value&gt; ...
caput -a [options] &lt;PV name&gt; &lt;no of elements&gt; &lt;value&gt; ...</pre>
<h4>Description</h4>
<p>Put value to a PV.</p>
<p>The specified value is written to the PV (as a string). The PV value is read
before and after the write operation and printed as "Old" and "new" values on
stdout.</p>
<p>The specified value is written to the PV (as a string). The PV's value is
read before and after the write operation and printed as "Old" and "New" values
on stdout.</p>
<p>The array variant writes an array to the specified PV. The first numeric
argument specifying the number of array elements is kept for compatibility with
the array data format of caget - the actual number of values specified on the
command line is used.</p>
<p>There are two variants to the arguments for this command. For the scalar
variant without the <code>-a</code> flag, all the value arguments provided after
the PV name are concatenated with a single space character between them, and the
resulting string (up to 40 characters long unless the <code>-S</code> flag is
given) is written to the specified PV.</p>
<p>The array variant with the <code>-a</code> flag writes an array of string
values to the specified PV. The numeric argument giving the number of array
elements is actually ignored, the array length to be written is actually
controlled by the number of values provided on the command line.</p>
<table border="1">
<caption></caption>
@@ -1550,12 +1566,16 @@ command line is used.</p>
<td>-t</td>
<td>Terse mode - print only successfully written value, without name</td>
</tr>
<tr>
<td>-l</td>
<td>Long mode "name timestamp value stat sevr" (read PVs as DBR_TIME_xxx)</td>
</tr>
<tr>
<td></td>
<td><strong>Enum Format:</strong></td>
</tr>
<tr>
<td></td>
<td>Default:</td>
<td>Auto - try value as ENUM string, then as index number</td>
</tr>
<tr>
@@ -1571,17 +1591,24 @@ command line is used.</p>
<td><strong>Arrays:</strong></td>
</tr>
<tr>
<td>-a</td>
<td>Put array data</td>
<td>Default:</td>
<td>Put scalar</td>
</tr>
<tr>
<td></td>
<td>Value format: Print number of requested values, then list of
values</td>
<td>Value format: all value arguments concatenated with spaces</td>
</tr>
<tr>
<td>-S</td>
<td>Put string as an array of char (long string)</td>
<td>Put string as an array of chars (long string)</td>
</tr>
<tr>
<td>-a</td>
<td>Put array</td>
</tr>
<tr>
<td></td>
<td>Value format: number of values, then list of values</td>
</tr>
</tbody>
</table>
@@ -2052,7 +2079,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
@@ -2076,16 +2103,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>
@@ -2258,7 +2285,7 @@ int main ( int argc, char ** argv )
unsigned nBytes;
unsigned elementCount;
char timeString[32];
unsigned i;
unsigned i;
chid chan;
double sum;
int status;
@@ -2301,7 +2328,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 );
@@ -2332,7 +2359,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 */
@@ -2355,7 +2382,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
@@ -2647,6 +2674,14 @@ 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>
@@ -2719,7 +2754,7 @@ time.</p>
</dl>
<dl>
<dt><code>USERFUNC</code></dt>
<dd>Optional address of the user's callback function to be run when the
<dd>Optional pointer to 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.
@@ -2792,6 +2827,12 @@ 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>
@@ -2806,16 +2847,16 @@ subscriptions (monitors) registered with the channel.</p>
<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>
@@ -2894,7 +2935,7 @@ but they do not cause the record to be processed.</p>
</dl>
<dl>
<dt><code>PFUNC</code></dt>
<dd>address of <a href="#User">user supplied callback function</a> to be
<dd>Pointer to a <a href="#User">user supplied callback function</a> to be
run when the requested operation completes</dd>
</dl>
<dl>
@@ -3002,7 +3043,7 @@ when a CA get request is initiated.</p>
</dl>
<dl>
<dt><code>USERFUNC</code></dt>
<dd>Address of <a href="#User">user supplied callback function</a> to be
<dd>Pointer to a <a href="#User">user supplied callback function</a> to be
run when the requested operation completes.</dd>
</dl>
<dl>
@@ -3042,7 +3083,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>
@@ -3103,8 +3144,8 @@ indicating the current state of the channel.</p>
<dd>channel identifier</dd>
</dl>
<dl>
<dt><code>USRERFUNC</code></dt>
<dd>The address of <a href="#User">user supplied callback function</a> to
<dt><code>USERFUNC</code></dt>
<dd>Pointer to a <a href="#User">user supplied callback function</a> to
be invoked with each subscription update.</dd>
</dl>
<dl>
@@ -3126,7 +3167,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>
@@ -3173,6 +3214,13 @@ 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>
@@ -3337,7 +3385,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>
@@ -3354,7 +3402,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
@@ -3378,7 +3426,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>
@@ -3402,7 +3450,7 @@ field should not be used.</p>
<h4>Arguments</h4>
<dl>
<dt><code>USERFUNC</code></dt>
<dd>Address of user callback function to be executed when an exceptions
<dd>Pointer to a user callback function to be executed when 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
@@ -3537,7 +3585,7 @@ default handler uses fprintf to send messages to 'stderr'.</p>
<h4>Arguments</h4>
<dl>
<dt><code>PFUNC</code></dt>
<dd>The address of a user supplied callback handler to be invoked when CA
<dd>A pointer to 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>
@@ -3585,9 +3633,9 @@ specified channel.</p>
</dl>
<dl>
<dt><code>PFUNC</code></dt>
<dd>Address of user supplied callback function. A null pointer uninstalls
<dd>Pointer to a 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;
@@ -3927,8 +3975,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>
@@ -3962,8 +4010,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>
@@ -4001,8 +4049,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>
@@ -4113,7 +4161,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>
@@ -4126,7 +4174,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
@@ -4267,7 +4315,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

@@ -127,21 +127,10 @@ 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

@@ -635,11 +635,13 @@ void cac::transferChanToVirtCircuit (
// must occur before moving to new iiu
pChan->getPIIU(guard)->uninstallChanDueToSuccessfulSearchResponse (
guard, *pChan, currentTime );
piiu->installChannel (
guard, *pChan, sid, typeCode, count );
if ( piiu ) {
piiu->installChannel (
guard, *pChan, sid, typeCode, count );
if ( newIIU ) {
piiu->start ( guard );
if ( newIIU ) {
piiu->start ( guard );
}
}
}
@@ -1304,9 +1306,11 @@ void cac::pvMultiplyDefinedNotify ( msgForMultiplyDefinedPV & mfmdpv,
callbackManager mgr ( this->notify, this->cbMutex );
epicsGuard < epicsMutex > guard ( this->mutex );
this->exception ( mgr.cbGuard, guard, ECA_DBLCHNL, buf, __FILE__, __LINE__ );
// remove from the list under lock
this->msgMultiPVList.remove ( mfmdpv );
}
// remove from the list and delete msg object
this->msgMultiPVList.remove ( mfmdpv );
// delete msg object
mfmdpv.~msgForMultiplyDefinedPV ();
this->mdpvFreeList.release ( & mfmdpv );
}

View File

@@ -24,7 +24,7 @@
DBE_ARCHIVE (DBE_LOG)
Trigger an event when an archive significant change in the channel's
valuue occurs. Relies on the archiver monitor deadband field under DCT.
value occurs. Relies on the archiver monitor deadband field under DCT.
DBE_ALARM
Trigger an event when the alarm state changes

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<http://www.aps.anl.gov/epics/base/R3-15/2-docs/CAref.html>
L<https://epics.anl.gov/base/R3-15/5-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 pod2htmd.tmp pod2htmi.tmp
CLEANS += Cap5.c
include $(TOP)/configure/RULES

View File

@@ -20,13 +20,16 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
HELP_MESSAGE() unless getopts('0:ac:d:e:f:F:g:hnsStw:');
HELP_MESSAGE() if $opt_h;
die "caget: -c option takes a positive number\n"
die "caget.pl: -c option takes a positive number\n"
unless looks_like_number($opt_c) && $opt_c >= 0;
die "No pv name specified. ('caget -h' gives help.)\n"
die "No pv name specified. ('caget.pl -h' gives help.)\n"
unless @ARGV;
my @chans = map { CA->new($_); } @ARGV;
my @chans = map { CA->new($_); } grep { $_ ne '' } @ARGV;
die "caget.pl: Please provide at least one non-empty pv name\n"
unless @chans;
eval { CA->pend_io($opt_w); };
if ($@) {
@@ -137,6 +140,10 @@ 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

@@ -16,10 +16,13 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
HELP_MESSAGE() unless getopts('hw:');
HELP_MESSAGE() if $opt_h;
die "No pv name specified. ('cainfo -h' gives help.)\n"
die "No pv name specified. ('cainfo.pl -h' gives help.)\n"
unless @ARGV;
my @chans = map { CA->new($_); } @ARGV;
my @chans = map { CA->new($_); } grep { $_ ne '' } @ARGV;
die "cainfo.pl: Please provide at least one non-empty pv name\n"
unless @chans;
eval {
CA->pend_io($opt_w);

View File

@@ -20,14 +20,17 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
HELP_MESSAGE() unless getopts('0:c:e:f:F:g:hm:nsSw:');
HELP_MESSAGE() if $opt_h;
die "caget: -c option takes a positive number\n"
die "camonitor.pl: -c option takes a positive number\n"
unless looks_like_number($opt_c) && $opt_c >= 0;
die "No pv name specified. ('camonitor -h' gives help.)\n"
die "No pv name specified. ('camonitor.pl -h' gives help.)\n"
unless @ARGV;
my %monitors;
my @chans = map { CA->new($_, \&conn_callback); } @ARGV;
my @chans = map { CA->new($_, \&conn_callback); } grep { $_ ne '' } @ARGV;
die "camonitor.pl: Please provide at least one non-empty pv name\n"
unless @chans;
my $fmt = ($opt_F eq ' ') ? "%-30s %s\n" : "%s$opt_F%s\n";

View File

@@ -17,11 +17,13 @@ $Getopt::Std::OUTPUT_HELP_VERSION = 1;
HELP_MESSAGE() unless getopts('achlnsStw:');
HELP_MESSAGE() if $opt_h;
die "No pv name specified. ('caput -h' gives help.)\n"
die "No pv name specified. ('caput.pl -h' gives help.)\n"
unless @ARGV;
my $pv = shift;
die "caput.pl: Empty pv name given.\n"
unless $pv ne '';
die "No value specified. ('caput -h' gives help.)\n"
die "No value specified. ('caput.pl -h' gives help.)\n"
unless @ARGV;
my $chan = CA->new($pv);

View File

@@ -504,6 +504,7 @@ void ca_repeater ()
if ( sockerrno == SOCK_EADDRINUSE ) {
osiSockRelease ();
debugPrintf ( ( "CA Repeater: exiting because a repeater is already running\n" ) );
delete [] pBuf;
return;
}
char sockErrBuf[64];

View File

@@ -541,11 +541,11 @@ int main (int argc, char *argv[])
for (n = 0; optind < argc; n++, optind++)
pvs[n].name = argv[optind] ; /* Copy PV names from command line */
connect_pvs(pvs, nPvs);
result = connect_pvs(pvs, nPvs);
/* Read and print data */
result = caget(pvs, nPvs, request, format, type, count);
if (!result)
result = caget(pvs, nPvs, request, format, type, count);
/* Shut down Channel Access */
ca_context_destroy();

View File

@@ -211,10 +211,11 @@ int main (int argc, char *argv[])
for (n = 0; optind < argc; n++, optind++)
pvs[n].name = argv[optind] ; /* Copy PV names from command line */
connect_pvs(pvs, nPvs);
result = connect_pvs(pvs, nPvs);
/* Print data */
result = cainfo(pvs, nPvs);
if (!result)
result = cainfo(pvs, nPvs);
/* Shut down Channel Access */
ca_context_destroy();

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.
\*************************************************************************/
/*
@@ -56,7 +56,7 @@ static epicsEventId epId;
void usage (void)
{
fprintf (stderr, "\nUsage: caput [options] <PV name> <PV value>\n"
fprintf (stderr, "\nUsage: caput [options] <PV name> <PV value> ...\n"
" caput -a [options] <PV name> <no of values> <PV value> ...\n\n"
" -h: Help: Print this message\n"
"Channel Access options:\n"
@@ -71,9 +71,11 @@ void usage (void)
" -n: Force interpretation of values as numbers\n"
" -s: Force interpretation of values as strings\n"
"Arrays:\n"
" Default: Put scalar\n"
" Value format: all value arguments concatenated with spaces\n"
" -S: Put string as an array of chars (long string)\n"
" -a: Put array\n"
" Value format: number of requested values, then list of values\n"
" -S: Put string as an array of char (long string)\n"
" Value format: number of values, then list of values\n"
"Alternate output field separator:\n"
" -F <ofs>: Use <ofs> as an alternate output field separator\n"
"\nExample: caput my_channel 1.2\n"
@@ -417,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]);
}
}
@@ -528,6 +530,11 @@ 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");
@@ -543,7 +550,7 @@ int main (int argc, char *argv[])
}
if (result != ECA_NORMAL) {
fprintf(stderr, "Error occured writing data.\n");
fprintf(stderr, "Error occured writing data: %s\n", ca_message(result));
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 */
"%ld" /* dec */,
"0" /* bin, val is 0 */,
"0o%lo" /* oct */,
"0x%lX" /* hex */
"%d" /* dec */,
"0" /* bin and val is 0 */,
"0o%o" /* oct */,
"0x%X" /* hex */
};
/* Formats have long modifier, pass value as a long */
sprintf(ret, fmt[outType], (long) val);
/* dbr_long_t is actually an int on all supported platforms */
sprintf(ret, fmt[outType], (int) val);
}
}
@@ -414,6 +414,12 @@ 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; \
@@ -506,12 +512,6 @@ 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

@@ -165,7 +165,7 @@ udpiiu::udpiiu (
#ifdef IP_ADD_MEMBERSHIP
{
int flag = 1;
osiSockOptMcastLoop_t flag = 1;
if ( setsockopt ( this->sock, IPPROTO_IP, IP_MULTICAST_LOOP,
(char *) &flag, sizeof ( flag ) ) == -1 ) {
char sockErrBuf[64];
@@ -915,10 +915,12 @@ bool udpiiu::pushDatagramMsg ( epicsGuard < epicsMutex > & guard,
caHdr * pbufmsg = ( caHdr * ) &this->xmitBuf[this->nBytesInXmitBuf];
*pbufmsg = msg;
memcpy ( pbufmsg + 1, pExt, extsize );
if ( extsize != alignedExtSize ) {
char *pDest = (char *) ( pbufmsg + 1 );
memset ( pDest + extsize, '\0', alignedExtSize - extsize );
if ( extsize ) {
memcpy ( pbufmsg + 1, pExt, extsize );
if ( extsize != alignedExtSize ) {
char *pDest = (char *) ( pbufmsg + 1 );
memset ( pDest + extsize, '\0', alignedExtSize - extsize );
}
}
AlignedWireRef < epicsUInt16 > ( pbufmsg->m_postsize ) = alignedExtSize;
this->nBytesInXmitBuf += msgsize;

View File

@@ -308,7 +308,7 @@ void gdd::test()
pdd->convertOffsetsToAddress();
pdd->dump();
pdd->unreference();
delete buf;
delete [] buf;
}
#endif
@@ -510,7 +510,7 @@ void gddContainer::test(void)
fprintf(stderr,"=====RE-DUMP OF ORIGINAL CONTAINER:\n");
dump();
cdd1->unreference();
delete buf;
delete [] buf;
// test copy(), Dup(), copyInfo()
fprintf(stderr,"=======CREATING TEST CONTAINER FOR *COPY* TEST:\n");

View File

@@ -74,10 +74,9 @@ LIBSRCS += casStreamIO.cc
LIBSRCS += ipIgnoreEntry.cc
# There is a bug in some vxWorks compilers that these work around:
ifeq ($(VX_GNU_VERSION), 4.1.2)
casStreamOS_CXXFLAGS_vxWorks-ppc604_altivec = -O0
casStreamOS_CXXFLAGS_vxWorks-ppc604_long = -O0
casStreamOS_CXXFLAGS_vxWorks-ppc604 = -O0
ifeq ($(VXWORKS_VERSION)$(filter -mcpu=604,$(ARCH_DEP_CFLAGS)), 6.6-mcpu=604)
casDGIntfOS_CXXFLAGS = -fno-inline
casStreamOS_CXXFLAGS = -fno-inline
endif
LIBSRCS_vxWorks += templateInstances.cpp

View File

@@ -170,7 +170,7 @@ static int parseDirectoryFP (FILE *pf, const char *pFileName)
status = aToIPAddr (hostNameStr, 0u, &ipa);
if (status) {
fprintf (pf, "Unknown host name=\"%s\" (or bad dotted ip addr) in \"%s\" with PV=\"%s\"?\n",
fprintf (stderr, "Unknown host name=\"%s\" (or bad dotted ip addr) in \"%s\" with PV=\"%s\"?\n",
hostNameStr, pFileName, pvNameStr);
return -1;
}

View File

@@ -21,6 +21,7 @@ casChannelI::casChannelI ( casCoreClient & clientIn,
casChannel & chanIn, casPVI & pvIn, ca_uint32_t cidIn ) :
privateForPV ( clientIn, *this ),
pv ( pvIn ),
maxElem( pvIn.nativeCount() ),
chan ( chanIn ),
cid ( cidIn ),
serverDeletePending ( false ),
@@ -29,7 +30,7 @@ casChannelI::casChannelI ( casCoreClient & clientIn,
}
casChannelI::~casChannelI ()
{
{
this->privateForPV.client().removeFromEventQueue (
*this, this->accessRightsEvPending );
@@ -48,7 +49,7 @@ void casChannelI::uninstallFromPV ( casEventSys & eventSys )
this->privateForPV.removeSelfFromPV ( this->pv, dest );
while ( casMonitor * pMon = dest.get () ) {
eventSys.prepareMonitorForDestroy ( *pMon );
}
}
}
void casChannelI::show ( unsigned level ) const
@@ -68,13 +69,13 @@ caStatus casChannelI::cbFunc (
{
caStatus stat = S_cas_success;
{
stat = this->privateForPV.client().accessRightsResponse (
stat = this->privateForPV.client().accessRightsResponse (
clientGuard, this );
}
if ( stat == S_cas_success ) {
this->accessRightsEvPending = false;
}
return stat;
if ( stat == S_cas_success ) {
this->accessRightsEvPending = false;
}
return stat;
}
caStatus casChannelI::read ( const casCtx & ctx, gdd & prototype )

View File

@@ -1,4 +1,3 @@
/*************************************************************************\
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
* National Laboratory.
@@ -31,55 +30,62 @@ class casChannelI : public tsDLNode < casChannelI >,
public:
casChannelI ( casCoreClient & clientIn, casChannel & chanIn,
casPVI & pvIn, ca_uint32_t cidIn );
~casChannelI ();
~casChannelI ();
void casChannelDestroyFromInterfaceNotify ();
const caResId getCID ();
const caResId getSID ();
const caResId getCID ();
const caResId getSID ();
void uninstallFromPV ( casEventSys & eventSys );
void installIntoPV ();
void installIO ( casAsyncIOI & );
void uninstallIO ( casAsyncIOI & );
void installMonitor ( casMonitor & mon );
casMonitor * removeMonitor ( ca_uint32_t clientIdIn );
casPVI & getPVI () const;
void clearOutstandingReads ();
void postAccessRightsEvent ();
casPVI & getPVI () const;
void clearOutstandingReads ();
void postAccessRightsEvent ();
const gddEnumStringTable & enumStringTable () const;
void setOwner ( const char * const pUserName,
const char * const pHostName );
bool readAccess () const;
ca_uint32_t getMaxElem () const;
void setOwner ( const char * const pUserName,
const char * const pHostName );
bool readAccess () const;
bool writeAccess () const;
bool confirmationRequested () const;
bool confirmationRequested () const;
caStatus read ( const casCtx & ctx, gdd & prototype );
caStatus write ( const casCtx & ctx, const gdd & value );
caStatus writeNotify ( const casCtx & ctx, const gdd & value );
void show ( unsigned level ) const;
void show ( unsigned level ) const;
private:
chanIntfForPV privateForPV;
tsDLList < casAsyncIOI > ioList;
casPVI & pv;
tsDLList < casAsyncIOI > ioList;
casPVI & pv;
ca_uint32_t maxElem;
casChannel & chan;
caResId cid; // client id
caResId cid; // client id
bool serverDeletePending;
bool accessRightsEvPending;
//epicsShareFunc virtual void destroy ();
caStatus cbFunc (
bool accessRightsEvPending;
//epicsShareFunc virtual void destroy ();
caStatus cbFunc (
casCoreClient &,
epicsGuard < casClientMutex > &,
epicsGuard < evSysMutex > & );
void postDestroyEvent ();
casChannelI ( const casChannelI & );
casChannelI & operator = ( const casChannelI & );
casChannelI ( const casChannelI & );
casChannelI & operator = ( const casChannelI & );
};
inline casPVI & casChannelI::getPVI () const
{
return this->pv;
return this->pv;
}
inline ca_uint32_t casChannelI::getMaxElem () const
{
return this->maxElem;
}
inline const caResId casChannelI::getCID ()
{
return this->cid;
return this->cid;
}
inline const caResId casChannelI::getSID ()
@@ -89,7 +95,7 @@ inline const caResId casChannelI::getSID ()
inline void casChannelI::postAccessRightsEvent ()
{
this->privateForPV.client().addToEventQueue ( *this, this->accessRightsEvPending );
this->privateForPV.client().addToEventQueue ( *this, this->accessRightsEvPending );
}
inline const gddEnumStringTable & casChannelI::enumStringTable () const
@@ -108,7 +114,7 @@ inline void casChannelI::clearOutstandingReads ()
}
inline void casChannelI::setOwner ( const char * const pUserName,
const char * const pHostName )
const char * const pHostName )
{
this->chan.setOwner ( pUserName, pHostName );
}

View File

@@ -24,39 +24,39 @@
casDGClient::pCASMsgHandler const casDGClient::msgHandlers[] =
{
& casDGClient::versionAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::versionAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::searchAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::echoAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::echoAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction,
& casDGClient::uknownMessageAction
};
//
@@ -84,7 +84,7 @@ casDGClient::~casDGClient()
//
void casDGClient::destroy()
{
printf("Attempt to destroy the DG client was ignored\n");
printf("Attempt to destroy the DG client was ignored\n");
}
//
@@ -92,16 +92,16 @@ void casDGClient::destroy()
//
void casDGClient::show (unsigned level) const
{
printf ( "casDGClient at %p\n",
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);
if (level>=1u) {
char buf[64];
this->hostName (buf, sizeof(buf));
printf ("Client Host=%s\n", buf);
this->casCoreClient::show ( level - 1u );
this->in.show ( level - 1u );
this->out.show ( level - 1u );
}
}
}
//
@@ -109,7 +109,7 @@ void casDGClient::show (unsigned level) const
//
caStatus casDGClient::uknownMessageAction ()
{
const caHdrLargeArray * mp = this->ctx.getMsg();
const caHdrLargeArray * mp = this->ctx.getMsg();
char pHostName[64u];
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
@@ -117,7 +117,7 @@ caStatus casDGClient::uknownMessageAction ()
caServerI::dumpMsg ( pHostName, "?", mp, this->ctx.getData(),
"bad request code=%u in DG\n", mp->m_cmmd );
return S_cas_badProtocol;
return S_cas_badProtocol;
}
//
@@ -125,9 +125,9 @@ caStatus casDGClient::uknownMessageAction ()
//
caStatus casDGClient::searchAction()
{
const caHdrLargeArray *mp = this->ctx.getMsg();
const caHdrLargeArray *mp = this->ctx.getMsg();
const char *pChanName = static_cast <char * > ( this->ctx.getData() );
caStatus status;
caStatus status;
//
// check the sanity of the message
@@ -135,7 +135,7 @@ caStatus casDGClient::searchAction()
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,7 +143,7 @@ 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;
}
@@ -155,56 +155,56 @@ caStatus casDGClient::searchAction()
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;
}
}
if ( this->getCAS().getDebugLevel() > 6u ) {
char pHostName[64u];
this->hostName ( pHostName, sizeof ( pHostName ) );
printf ( "\"%s\" is searching for \"%s\"\n",
if ( this->getCAS().getDebugLevel() > 6u ) {
char pHostName[64u];
this->hostName ( pHostName, sizeof ( pHostName ) );
printf ( "\"%s\" is searching for \"%s\"\n",
pHostName, pChanName );
}
}
//
// verify that we have sufficent memory for a PV and a
// monitor prior to calling PV exist test so that when
// the server runs out of memory we dont reply to
// search requests, and therefore dont thrash through
// caServer::pvExistTest() and casCreatePV::pvAttach()
//
//
// verify that we have sufficent memory for a PV and a
// monitor prior to calling PV exist test so that when
// the server runs out of memory we dont reply to
// search requests, and therefore dont thrash through
// caServer::pvExistTest() and casCreatePV::pvAttach()
//
if ( ! osiSufficentSpaceInPool ( 0 ) ) {
return S_cas_success;
}
//
// ask the server tool if this PV exists
//
this->userStartedAsyncIO = false;
pvExistReturn pver =
this->getCAS()->pvExistTest ( this->ctx, this->lastRecvAddr, pChanName );
//
// ask the server tool if this PV exists
//
this->userStartedAsyncIO = false;
pvExistReturn pver =
this->getCAS()->pvExistTest ( this->ctx, this->lastRecvAddr, pChanName );
//
// prevent problems when they initiate
// async IO but dont return status
// indicating so (and vise versa)
//
if ( this->userStartedAsyncIO ) {
//
// prevent problems when they initiate
// async IO but dont return status
// indicating so (and vise versa)
//
if ( this->userStartedAsyncIO ) {
if ( pver.getStatus() != pverAsyncCompletion ) {
errMessage (S_cas_badParameter,
"- assuming asynch IO status from caServer::pvExistTest()");
errMessage (S_cas_badParameter,
"- assuming asynch IO status from caServer::pvExistTest()");
}
status = S_cas_success;
}
else {
//
// otherwise we assume sync IO operation was initiated
//
}
else {
//
// otherwise we assume sync IO operation was initiated
//
switch ( pver.getStatus() ) {
case pverExistsHere:
status = this->searchResponse (*mp, pver);
status = this->searchResponse (*mp, pver);
break;
case pverDoesNotExistHere:
@@ -212,18 +212,18 @@ caStatus casDGClient::searchAction()
break;
case pverAsyncCompletion:
errMessage (S_cas_badParameter,
"- unexpected asynch IO status from caServer::pvExistTest() ignored");
errMessage (S_cas_badParameter,
"- unexpected asynch IO status from caServer::pvExistTest() ignored");
status = S_cas_success;
break;
default:
errMessage (S_cas_badParameter,
"- invalid return from caServer::pvExistTest() ignored");
errMessage (S_cas_badParameter,
"- invalid return from caServer::pvExistTest() ignored");
status = S_cas_success;
break;
}
}
}
}
return status;
}
@@ -340,9 +340,9 @@ caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
}
//
// casDGClient::searchFailResponse()
// (only when requested by the client
// - when it isnt a reply to a broadcast)
// casDGClient::searchFailResponse()
// (only when requested by the client
// - when it isnt a reply to a broadcast)
//
caStatus casDGClient::searchFailResponse ( const caHdrLargeArray * mp )
{
@@ -350,9 +350,9 @@ caStatus casDGClient::searchFailResponse ( const caHdrLargeArray * mp )
this->out.copyInHeader ( CA_PROTO_NOT_FOUND, 0,
mp->m_dataType, mp->m_count, mp->m_cid, mp->m_available, 0 );
this->out.commitMsg ();
this->out.commitMsg ();
return S_cas_success;
return S_cas_success;
}
/*
@@ -360,7 +360,7 @@ caStatus casDGClient::searchFailResponse ( const caHdrLargeArray * mp )
*/
caStatus casDGClient::versionAction ()
{
const caHdrLargeArray * mp = this->ctx.getMsg();
const caHdrLargeArray * mp = this->ctx.getMsg();
if ( mp->m_count != 0 ) {
this->minor_version_number = static_cast <ca_uint16_t> ( mp->m_count );
@@ -371,7 +371,7 @@ caStatus casDGClient::versionAction ()
this->seqNoOfReq = 0;
}
}
return S_cas_success;
return S_cas_success;
}
//
@@ -380,25 +380,25 @@ caStatus casDGClient::versionAction ()
//
void casDGClient::sendBeacon ( ca_uint32_t beaconNumber )
{
union {
caHdr msg;
char buf;
};
union {
caHdr msg;
char buf;
};
//
// create the message
//
memset ( & buf, 0, sizeof ( msg ) );
//
// create the message
//
memset ( & buf, 0, sizeof ( msg ) );
AlignedWireRef < epicsUInt16 > ( msg.m_cmmd ) = CA_PROTO_RSRV_IS_UP;
AlignedWireRef < epicsUInt16 > ( msg.m_dataType ) = CA_MINOR_PROTOCOL_REVISION;
AlignedWireRef < epicsUInt32 > ( msg.m_cid ) = beaconNumber;
//
// send it to all addresses on the beacon list,
//
// send it to all addresses on the beacon list,
// but let the IO specific code set the address
// field and the port field
//
this->sendBeaconIO ( buf, sizeof (msg), msg.m_count, msg.m_available );
//
this->sendBeaconIO ( buf, sizeof (msg), msg.m_count, msg.m_available );
}
//
@@ -419,8 +419,8 @@ outBufClient::flushCondition casDGClient::xSend ( char *pBufIn,
if ( pHdr->cadg_addr.isValid() ) {
outBufClient::flushCondition stat =
this->osdSend ( pDG, sizeDG, pHdr->cadg_addr );
if ( stat != outBufClient::flushProgress ) {
this->osdSend ( pDG, sizeDG, pHdr->cadg_addr );
if ( stat != outBufClient::flushProgress ) {
break;
}
}
@@ -429,10 +429,10 @@ outBufClient::flushCondition casDGClient::xSend ( char *pBufIn,
}
if ( totalBytes ) {
//
// !! this time fetch may be slowing things down !!
//
//this->lastSendTS = epicsTime::getCurrent();
//
// !! this time fetch may be slowing things down !!
//
//this->lastSendTS = epicsTime::getCurrent();
nBytesSent = totalBytes;
return outBufClient::flushProgress;
}
@@ -455,16 +455,16 @@ 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) {
if (stat==casFillProgress) {
pHdr->cadg_nBytes = nDGBytesRecv + sizeof(*pHdr);
pCurBuf += pHdr->cadg_nBytes;
//
// !! this time fetch may be slowing things down !!
//
//this->lastRecvTS = epicsTime::getCurrent();
}
//
// !! this time fetch may be slowing things down !!
//
//this->lastRecvTS = epicsTime::getCurrent();
}
else {
break;
}
@@ -515,7 +515,7 @@ caStatus casDGClient::asyncSearchResponse (
pMsg->m_dataType = htons ( sequenceNoIsValid );
}
caStatus stat = this->searchResponse ( msg, retVal );
caStatus stat = this->searchResponse ( msg, retVal );
pRespHdr->cadg_nBytes = this->out.popCtx (outctx) + sizeof ( *pRespHdr );
if ( pRespHdr->cadg_nBytes > sizeof ( *pRespHdr ) + sizeof (caHdr) ) {
@@ -523,7 +523,7 @@ caStatus casDGClient::asyncSearchResponse (
this->out.commitRawMsg ( pRespHdr->cadg_nBytes );
}
return stat;
return stat;
}
//
@@ -644,6 +644,11 @@ 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;
}
@@ -653,7 +658,7 @@ caStatus casDGClient::processDG ()
//
unsigned casDGClient::getDebugLevel() const
{
return this->getCAS().getDebugLevel();
return this->getCAS().getDebugLevel();
}
//
@@ -661,7 +666,7 @@ unsigned casDGClient::getDebugLevel() const
//
caNetAddr casDGClient::fetchLastRecvAddr () const
{
return this->lastRecvAddr;
return this->lastRecvAddr;
}
//
@@ -669,7 +674,7 @@ caNetAddr casDGClient::fetchLastRecvAddr () const
//
ca_uint32_t casDGClient::datagramSequenceNumber () const
{
return this->seqNoOfReq;
return this->seqNoOfReq;
}
//
@@ -729,27 +734,27 @@ outBufClient::flushCondition casDGClient::flush ()
//
caStatus casDGClient::processMsg ()
{
int status = S_cas_success;
int status = S_cas_success;
try {
unsigned bytesLeft;
while ( ( bytesLeft = this->in.bytesPresent() ) ) {
unsigned bytesLeft;
while ( ( bytesLeft = this->in.bytesPresent() ) ) {
caHdrLargeArray msgTmp;
unsigned msgSize;
ca_uint32_t hdrSize;
char * rawMP;
{
//
// copy as raw bytes in order to avoid
// alignment problems
//
//
// copy as raw bytes in order to avoid
// alignment problems
//
caHdr smallHdr;
if ( bytesLeft < sizeof ( smallHdr ) ) {
break;
}
rawMP = this->in.msgPtr ();
memcpy ( & smallHdr, rawMP, sizeof ( smallHdr ) );
memcpy ( & smallHdr, rawMP, sizeof ( smallHdr ) );
ca_uint32_t payloadSize = AlignedWireRef < epicsUInt16 > ( smallHdr.m_postsize );
ca_uint32_t nElem = AlignedWireRef < epicsUInt16 > ( smallHdr.m_count );
@@ -798,45 +803,45 @@ caStatus casDGClient::processMsg ()
this->ctx.setMsg ( msgTmp, rawMP + hdrSize );
if ( this->getCAS().getDebugLevel() > 5u ) {
if ( this->getCAS().getDebugLevel() > 5u ) {
char pHostName[64u];
this->lastRecvAddr.stringConvert ( pHostName, sizeof ( pHostName ) );
caServerI::dumpMsg ( pHostName, "?",
caServerI::dumpMsg ( pHostName, "?",
& msgTmp, rawMP + hdrSize, 0 );
}
}
}
//
// Reset the context to the default
// (guarantees that previous message does not get mixed
// up with the current message)
//
this->ctx.setChannel ( NULL );
this->ctx.setPV ( NULL );
//
// Reset the context to the default
// (guarantees that previous message does not get mixed
// up with the current message)
//
this->ctx.setChannel ( NULL );
this->ctx.setPV ( NULL );
//
// Call protocol stub
//
//
// Call protocol stub
//
casDGClient::pCASMsgHandler pHandler;
if ( msgTmp.m_cmmd < NELEMENTS ( casDGClient::msgHandlers ) ) {
if ( msgTmp.m_cmmd < NELEMENTS ( casDGClient::msgHandlers ) ) {
pHandler = this->casDGClient::msgHandlers[msgTmp.m_cmmd];
}
}
else {
pHandler = & casDGClient::uknownMessageAction;
}
status = ( this->*pHandler ) ();
if ( status ) {
status = ( this->*pHandler ) ();
if ( status ) {
this->in.removeMsg ( this->in.bytesPresent() );
break;
}
break;
}
this->in.removeMsg ( msgSize );
}
}
}
catch ( std::exception & except ) {
this->in.removeMsg ( this->in.bytesPresent() );
status = this->sendErr (
this->sendErr (
this->ctx.getMsg(), invalidResID, ECA_INTERNAL,
"C++ exception \"%s\" in CA circuit server",
except.what () );
@@ -844,13 +849,13 @@ caStatus casDGClient::processMsg ()
}
catch (...) {
this->in.removeMsg ( this->in.bytesPresent() );
status = this->sendErr (
this->sendErr (
this->ctx.getMsg(), invalidResID, ECA_INTERNAL,
"unexpected C++ exception in CA datagram server" );
status = S_cas_internal;
}
return status;
return status;
}
//
@@ -859,24 +864,25 @@ caStatus casDGClient::processMsg ()
caStatus casDGClient::sendErr ( const caHdrLargeArray *curp,
ca_uint32_t cid, const int reportedStatus, const char *pformat, ... )
{
unsigned stringSize;
char msgBuf[1024]; /* allocate plenty of space for the message string */
if ( pformat ) {
va_list args;
va_start ( args, pformat );
int status = vsprintf ( msgBuf, pformat, args );
if ( status < 0 ) {
errPrintf (S_cas_internal, __FILE__, __LINE__,
"bad sendErr(%s)", pformat);
stringSize = 0u;
}
else {
stringSize = 1u + (unsigned) status;
}
}
else {
stringSize = 0u;
}
unsigned stringSize;
char msgBuf[1024]; /* allocate plenty of space for the message string */
if ( pformat ) {
va_list args;
va_start ( args, pformat );
int status = vsprintf ( msgBuf, pformat, args );
if ( status < 0 ) {
errPrintf (S_cas_internal, __FILE__, __LINE__,
"bad sendErr(%s)", pformat);
stringSize = 0u;
}
else {
stringSize = 1u + (unsigned) status;
}
va_end ( args );
}
else {
stringSize = 0u;
}
unsigned hdrSize = sizeof ( caHdr );
if ( ( curp->m_postsize >= 0xffff || curp->m_count >= 0xffff ) &&
@@ -927,7 +933,7 @@ caStatus casDGClient::sendErr ( const caHdrLargeArray *curp,
this->out.commitMsg ();
}
return S_cas_success;
return S_cas_success;
}
@@ -936,8 +942,8 @@ caStatus casDGClient::sendErr ( const caHdrLargeArray *curp,
//
caStatus casDGClient::echoAction ()
{
const caHdrLargeArray * mp = this->ctx.getMsg();
const void * dp = this->ctx.getData();
const caHdrLargeArray * mp = this->ctx.getMsg();
const void * dp = this->ctx.getData();
void * pPayloadOut;
epicsGuard < epicsMutex > guard ( this->mutex );
@@ -948,5 +954,5 @@ caStatus casDGClient::echoAction ()
memcpy ( pPayloadOut, dp, mp->m_postsize );
this->out.commitMsg ();
}
return S_cas_success;
return S_cas_success;
}

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,33 +26,39 @@
#include "casAsyncIOI.h"
#include "casMonitor.h"
casPVI::casPVI ( casPV & intf ) :
pCAS ( NULL ), pPV ( & intf ), nMonAttached ( 0u ),
// 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 ),
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 ( "The number of IO objected attached is %u\n", this->nIOAttached );
errlogPrintf ( "%u IO objects still attached in destructor\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 );
@@ -139,26 +145,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 ) {
errMessage ( S_cas_noMemory,
casErrMessage ( 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 ();
errMessage ( status,
"unable to to config gdd for read of application type \"enums\" string"
" conversion table for enumerated PV");
casErrMessage ( status,
"unable to config gdd for read of application type \"enums\" string"
" conversion table for enumerated PV" );
return status;
}
@@ -169,12 +175,11 @@ 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 ) {
errPrintf ( status, __FILE__, __LINE__,
"- unable to read application type \"enums\" "
" (string conversion table) from enumerated native type PV \"%s\"",
this->getName() );
casErrMessage ( status,
"unable to read application type \"enums\" "
" (string conversion table) from enumerated native type PV" );
}
pTmp->unreference ();
@@ -185,40 +190,39 @@ caStatus casPVI::updateEnumStringTable ( casCtx & ctxIn )
void casPVI::updateEnumStringTableAsyncCompletion ( const gdd & resp )
{
epicsGuard < epicsMutex > guard ( this->mutex );
if ( resp.isContainer() ) {
errMessage ( S_cas_badType,
"application type \"enums\" string conversion table for"
" enumerated PV was a container (expected vector of strings)" );
casErrMessage ( S_cas_badType,
"Invalid \"enums\" string conversion table for"
" enumerated PV (container instead of vector of strings)" );
return;
}
if ( resp.dimension() == 0 ) {
if ( resp.primitiveType() == aitEnumString ) {
aitString *pStr = (aitString *) resp.dataVoid ();
if ( ! this->enumStrTbl.setString ( 0, pStr->string() ) ) {
errMessage ( S_cas_noMemory,
casErrMessage ( 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 ) ) {
errMessage ( S_cas_noMemory,
casErrMessage ( S_cas_noMemory,
"no memory to set enumerated PV string cache" );
}
}
else {
errPrintf ( S_cas_badType, __FILE__, __LINE__,
casErrMessage ( S_cas_badType,
"application type \"enums\" string conversion"
" table for enumerated PV \"%s\" isnt a string type?",
getName() );
" table for enumerated PV isnt a string type?" );
}
}
else if ( resp.dimension() == 1 ) {
gddStatus gdd_status;
aitIndex index, first, count;
gdd_status = resp.getBound ( 0, first, count );
assert ( gdd_status == 0 );
@@ -232,7 +236,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() ) ) {
errMessage ( S_cas_noMemory,
casErrMessage ( S_cas_noMemory,
"no memory to set enumerated PV string cache" );
}
}
@@ -241,19 +245,18 @@ 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 ) ) {
errMessage ( S_cas_noMemory,
casErrMessage ( S_cas_noMemory,
"no memory to set enumerated PV string cache" );
}
}
}
else {
errMessage ( S_cas_badType,
"application type \"enums\" string conversion"
" table for enumerated PV isnt a string type?" );
casErrMessage( S_cas_badType,
"bad \"enums\" string conversion table for enumerated PV" );
}
}
else {
errMessage ( S_cas_badType,
casErrMessage ( S_cas_badType,
"application type \"enums\" string conversion table"
" for enumerated PV was multi-dimensional"
" (expected vector of strings)" );
@@ -287,7 +290,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 );
@@ -303,14 +306,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 ();
@@ -359,9 +362,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 );
@@ -380,8 +383,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;
@@ -407,7 +410,7 @@ void casPVI::destroyAllIO ( tsDLList < casAsyncIOI > & ioList )
}
}
void casPVI::installIO (
void casPVI::installIO (
tsDLList < casAsyncIOI > & ioList, casAsyncIOI & io )
{
epicsGuard < epicsMutex > guard ( this->mutex );
@@ -416,7 +419,7 @@ void casPVI::installIO (
this->nIOAttached++;
}
void casPVI::uninstallIO (
void casPVI::uninstallIO (
tsDLList < casAsyncIOI > & ioList, casAsyncIOI & io )
{
{
@@ -517,8 +520,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 ) {
@@ -542,4 +545,3 @@ const char * casPVI::getName () const
return "<disconnected>";
}
}

View File

@@ -409,7 +409,7 @@ caStatus casStrmClient::verifyRequest (casChannelI * & pChan , bool allowdyn)
//
// element count out of range ?
//
if ( ctx.msg.m_count > pChan->getPVI().nativeCount() ||
if ( ctx.msg.m_count > pChan->getMaxElem() ||
( !allowdyn && ctx.msg.m_count == 0u ) ) {
return ECA_BADCOUNT;
}
@@ -530,8 +530,20 @@ caStatus casStrmClient::readResponse ( epicsGuard < casClientMutex > & guard,
pChan->getCID(), status, ECA_GETFAIL );
}
aitUint32 elementCount = 0;
if (desc.isContainer()) {
aitUint32 index;
int gdds = gddApplicationTypeTable::app_table.mapAppToIndex
( desc.applicationType(), gddAppType_value, index );
if ( gdds ) {
return S_cas_badType;
}
elementCount = desc.getDD(index)->getDataSizeElements();
} else {
elementCount = desc.getDataSizeElements();
}
ca_uint32_t count = (msg.m_count == 0) ?
(ca_uint32_t)desc.getDataSizeElements() :
(ca_uint32_t)elementCount :
msg.m_count;
void * pPayload;
@@ -659,8 +671,20 @@ caStatus casStrmClient::readNotifyResponse ( epicsGuard < casClientMutex > & gua
return ecaStatus;
}
aitUint32 elementCount = 0;
if (desc.isContainer()) {
aitUint32 index;
int gdds = gddApplicationTypeTable::app_table.mapAppToIndex
( desc.applicationType(), gddAppType_value, index );
if ( gdds ) {
return S_cas_badType;
}
elementCount = desc.getDD(index)->getDataSizeElements();
} else {
elementCount = desc.getDataSizeElements();
}
ca_uint32_t count = (msg.m_count == 0) ?
(ca_uint32_t)desc.getDataSizeElements() :
(ca_uint32_t)elementCount :
msg.m_count;
void *pPayload;
@@ -856,8 +880,20 @@ caStatus casStrmClient::monitorResponse (
casChannelI & chan, const caHdrLargeArray & msg,
const gdd & desc, const caStatus completionStatus )
{
aitUint32 elementCount = 0;
if (desc.isContainer()) {
aitUint32 index;
int gdds = gddApplicationTypeTable::app_table.mapAppToIndex
( desc.applicationType(), gddAppType_value, index );
if ( gdds ) {
return S_cas_badType;
}
elementCount = desc.getDD(index)->getDataSizeElements();
} else {
elementCount = desc.getDataSizeElements();
}
ca_uint32_t count = (msg.m_count == 0) ?
(ca_uint32_t)desc.getDataSizeElements() :
(ca_uint32_t)elementCount :
msg.m_count;
void * pPayload = 0;
@@ -883,7 +919,7 @@ caStatus casStrmClient::monitorResponse (
gdd * pDBRDD = 0;
if ( completionStatus == S_cas_success ) {
caStatus status = createDBRDD ( msg.m_dataType, count,
chan.getPVI().nativeCount(), pDBRDD );
chan.getMaxElem(), pDBRDD );
if ( status != S_cas_success ) {
caStatus ecaStatus;
if ( status == S_cas_badType ) {
@@ -1854,7 +1890,7 @@ caStatus casStrmClient::privateCreateChanResponse (
// the protocol buffer.
//
assert ( nativeTypeDBR <= 0xffff );
aitIndex nativeCount = chan.getPVI().nativeCount();
aitIndex nativeCount = chan.getMaxElem();
assert ( nativeCount <= 0xffffffff );
assert ( hdr.m_cid == chan.getCID() );
status = this->out.copyInHeader ( CA_PROTO_CREATE_CHAN, 0,
@@ -2614,7 +2650,7 @@ caStatus casStrmClient::read ()
{
gdd * pDD = 0;
caStatus status = createDBRDD ( pHdr->m_dataType, pHdr->m_count,
this->ctx.getChannel()->getPVI().nativeCount(), pDD );
this->ctx.getChannel()->getMaxElem(), pDD );
if ( status != S_cas_success ) {
return status;
}
@@ -2761,6 +2797,7 @@ caStatus casStrmClient::sendErr ( epicsGuard <casClientMutex> &,
else {
stringSize = 1u + (unsigned) status;
}
va_end ( args );
}
else {
stringSize = 0u;

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.
\*************************************************************************/
//
@@ -32,7 +32,7 @@ const unsigned caServerConnectPendQueueSize = 5u;
//
// casIntfIO::casIntfIO()
//
casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
sock ( INVALID_SOCKET ),
addr ( addrIn.getSockIP() )
{
@@ -40,80 +40,79 @@ casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
osiSocklen_t addrSize;
bool portChange;
if ( ! osiSockAttach () ) {
throw S_cas_internal;
}
if ( ! osiSockAttach () ) {
throw S_cas_internal;
}
/*
* Setup the server socket
*/
this->sock = epicsSocketCreate ( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if (this->sock==INVALID_SOCKET) {
/*
* Setup the server socket
*/
this->sock = epicsSocketCreate ( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if (this->sock == INVALID_SOCKET) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
printf ( "No socket error was %s\n", sockErrBuf );
throw S_cas_noFD;
}
printf ( "No socket error was %s\n", sockErrBuf );
throw S_cas_noFD;
}
epicsSocketEnableAddressReuseDuringTimeWaitState ( this->sock );
status = bind ( this->sock,
reinterpret_cast <sockaddr *> (&this->addr),
sizeof(this->addr) );
if (status<0) {
if (SOCKERRNO == SOCK_EADDRINUSE) {
//
// enable assignment of a default port
// (so the getsockname() call below will
// work correctly)
//
this->addr.sin_port = ntohs (0);
status = bind(
status = bind ( this->sock,
reinterpret_cast <sockaddr *> (&this->addr),
sizeof(this->addr) );
if (status < 0) {
if (SOCKERRNO == SOCK_EADDRINUSE ||
SOCKERRNO == SOCK_EACCES) {
//
// enable assignment of a default port
// (so the getsockname() call below will
// work correctly)
//
this->addr.sin_port = ntohs (0);
status = bind(
this->sock,
reinterpret_cast <sockaddr *> (&this->addr),
sizeof(this->addr) );
}
if (status<0) {
}
if (status < 0) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
char buf[64];
ipAddrToA (&this->addr, buf, sizeof(buf));
errPrintf ( S_cas_bindFail,
__FILE__, __LINE__,
"- bind TCP IP addr=%s failed because %s",
buf, sockErrBuf );
char buf[64];
ipAddrToA (&this->addr, buf, sizeof(buf));
errlogPrintf ( "CAS: Socket bind TCP to %s failed with %s",
buf, sockErrBuf );
epicsSocketDestroy (this->sock);
throw S_cas_bindFail;
}
throw S_cas_bindFail;
}
portChange = true;
}
}
else {
portChange = false;
}
addrSize = ( osiSocklen_t ) sizeof (this->addr);
status = getsockname (
this->sock,
reinterpret_cast <sockaddr *> ( &this->addr ),
addrSize = ( osiSocklen_t ) sizeof (this->addr);
status = getsockname (
this->sock,
reinterpret_cast <sockaddr *> ( &this->addr ),
&addrSize );
if (status) {
if (status) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
errlogPrintf ( "CAS: getsockname() error %s\n",
sockErrBuf );
errlogPrintf ( "CAS: getsockname() error %s\n",
sockErrBuf );
epicsSocketDestroy (this->sock);
throw S_cas_internal;
}
throw S_cas_internal;
}
//
// be sure of this now so that we can fetch the IP
// address and port number later
//
//
// be sure of this now so that we can fetch the IP
// address and port number later
//
assert (this->addr.sin_family == AF_INET);
if ( portChange ) {
errlogPrintf ( "cas warning: Configured TCP port was unavailable.\n");
errlogPrintf ( "cas warning: Using dynamically assigned TCP port %hu,\n",
errlogPrintf ( "cas warning: Using dynamically assigned TCP port %hu,\n",
ntohs (this->addr.sin_port) );
errlogPrintf ( "cas warning: but now two or more servers share the same UDP port.\n");
errlogPrintf ( "cas warning: Depending on your IP kernel this server may not be\n" );
@@ -121,12 +120,12 @@ casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
}
status = listen(this->sock, caServerConnectPendQueueSize);
if(status < 0) {
if (status < 0) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
errlogPrintf ( "CAS: listen() error %s\n", sockErrBuf );
errlogPrintf ( "CAS: listen() error %s\n", sockErrBuf );
epicsSocketDestroy (this->sock);
throw S_cas_internal;
throw S_cas_internal;
}
}
@@ -135,17 +134,17 @@ casIntfIO::casIntfIO ( const caNetAddr & addrIn ) :
//
casIntfIO::~casIntfIO()
{
if (this->sock != INVALID_SOCKET) {
epicsSocketDestroy (this->sock);
}
if (this->sock != INVALID_SOCKET) {
epicsSocketDestroy (this->sock);
}
osiSockRelease ();
osiSockRelease ();
}
//
// newStreamIO::newStreamClient()
//
casStreamOS *casIntfIO::newStreamClient ( caServerI & cas,
casStreamOS *casIntfIO::newStreamClient ( caServerI & cas,
clientBufMemoryManager & bufMgr ) const
{
static bool oneMsgFlag = false;
@@ -175,14 +174,14 @@ casStreamOS *casIntfIO::newStreamClient ( caServerI & cas,
args.sock = newSock;
casStreamOS * pOS = new casStreamOS ( cas, bufMgr, args );
if ( ! pOS ) {
errMessage ( S_cas_noMemory,
errMessage ( S_cas_noMemory,
"unable to create data structures for a new client" );
epicsSocketDestroy ( newSock );
}
else {
if ( cas.getDebugLevel() > 0u ) {
char pName[64u];
pOS->hostName ( pName, sizeof ( pName ) );
errlogPrintf ( "CAS: allocated client object for \"%s\"\n", pName );
}
@@ -197,7 +196,7 @@ void casIntfIO::setNonBlocking()
{
int status;
osiSockIoctl_t yes = true;
status = socket_ioctl(this->sock, FIONBIO, &yes);
if ( status < 0 ) {
char sockErrBuf[64];

View File

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

View File

@@ -46,6 +46,7 @@
#include "epicsExport.h"
#include "link.h"
#include "recSup.h"
#include "dbUnitTest.h" /* for testSyncCallback() */
static int callbackQueueSize = 2000;
@@ -81,6 +82,10 @@ 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,
@@ -284,11 +289,7 @@ int callbackRequest(CALLBACK *pcallback)
pushOK = epicsRingPointerPush(mySet->queue, pcallback);
if (!pushOK) {
char msg[48] = "callbackRequest: ";
strcat(msg, threadNamePrefix[priority]);
strcat(msg, " ring buffer full\n");
epicsInterruptContextMessage(msg);
epicsInterruptContextMessage(fullMessage[priority]);
mySet->queueOverflow = TRUE;
return S_db_bufFull;
}
@@ -353,3 +354,86 @@ 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,7 +42,9 @@ typedef struct callbackPvt {
int priority;
void *user; /*for use by callback user*/
void *timer; /*for use by callback itself*/
}CALLBACK;
}epicsCallback;
typedef epicsCallback CALLBACK;
typedef void (*CALLBACKFUNC)(struct callbackPvt*);

View File

@@ -291,10 +291,14 @@ 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 = (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;
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;
if (no_data)
*options ^= DBR_AL_LONG; /*Turn off option*/
@@ -738,28 +742,34 @@ static long getLinkValue(DBADDR *paddr, short dbrType,
{
dbCommon *precord = paddr->precord;
dbFldDes *pfldDes = paddr->pfldDes;
/* size of pbuf storage in bytes, including space for trailing nil */
int maxlen;
DBENTRY dbEntry;
long status;
long nReq = nRequest ? *nRequest : 1;
/* dbFindRecord() below will always succeed as we have a
* valid DBADDR, so no point to check again.
* Request for zero elements always succeeds
*/
if(!nReq)
return 0;
switch (dbrType) {
case DBR_STRING:
maxlen = MAX_STRING_SIZE - 1;
if (nRequest && *nRequest > 1) *nRequest = 1;
maxlen = MAX_STRING_SIZE;
nReq = 1;
break;
case DBR_DOUBLE: /* Needed for dbCa links */
if (nRequest && *nRequest) *nRequest = 1;
if (nRequest) *nRequest = 1;
*(double *)pbuf = epicsNAN;
return 0;
case DBR_CHAR:
case DBR_UCHAR:
if (nRequest && *nRequest > 0) {
maxlen = *nRequest - 1;
break;
}
/* else fall through ... */
maxlen = nReq;
break;
default:
return S_db_badDbrtype;
}
@@ -768,10 +778,13 @@ static long getLinkValue(DBADDR *paddr, short dbrType,
status = dbFindRecord(&dbEntry, precord->name);
if (!status) status = dbFindField(&dbEntry, pfldDes->name);
if (!status) {
char *rtnString = dbGetString(&dbEntry);
const char *rtnString = dbGetString(&dbEntry);
strncpy(pbuf, rtnString, --maxlen);
pbuf[maxlen] = 0;
strncpy(pbuf, rtnString, maxlen-1);
pbuf[maxlen-1] = 0;
if(dbrType!=DBR_STRING)
nReq = strlen(pbuf)+1;
if(nRequest) *nRequest = nReq;
}
dbFinishEntry(&dbEntry);
return status;
@@ -781,28 +794,31 @@ static long getAttrValue(DBADDR *paddr, short dbrType,
char *pbuf, long *nRequest)
{
int maxlen;
long nReq = nRequest ? *nRequest : 1;
if (!paddr->pfield) return S_db_badField;
switch (dbrType) {
case DBR_STRING:
maxlen = MAX_STRING_SIZE - 1;
if (nRequest && *nRequest > 1) *nRequest = 1;
maxlen = MAX_STRING_SIZE;
nReq = 1;
break;
case DBR_CHAR:
case DBR_UCHAR:
if (nRequest && *nRequest > 0) {
maxlen = *nRequest - 1;
break;
}
maxlen = nReq;
break;
/* else fall through ... */
default:
return S_db_badDbrtype;
}
strncpy(pbuf, paddr->pfield, --maxlen);
pbuf[maxlen] = 0;
strncpy(pbuf, paddr->pfield, maxlen-1);
pbuf[maxlen-1] = 0;
if(dbrType!=DBR_STRING)
nReq = strlen(pbuf)+1;
if(nRequest) *nRequest = nReq;
return 0;
}
@@ -930,6 +946,15 @@ long dbGet(DBADDR *paddr, short dbrType,
localAddr.pfield = (char *) pfl->u.r.field;
status = convert(&localAddr, pbuf, n, capacity, offset);
}
if(!status && dbrType==DBF_CHAR && nRequest &&
paddr->pfldDes && paddr->pfldDes->field_type==DBF_STRING)
{
/* long string ensure nil and truncate to actual length */
long nReq = *nRequest;
pbuf[nReq-1] = '\0';
*nRequest = strlen(pbuf)+1;
}
}
done:
paddr->pfield = pfieldsave;

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

@@ -144,7 +144,6 @@ static void addAction(caLink *pca, short link_action)
if (++removesOutstanding >= removesOutstandingWarning) {
errlogPrintf("dbCa::addAction pausing, %d channels to clear\n",
removesOutstanding);
printLinks(pca);
}
while (removesOutstanding >= removesOutstandingWarning) {
epicsMutexUnlock(workListLock);
@@ -650,11 +649,16 @@ 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)) {
/* 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 */
/* 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;
}
plink->value.pv_link.pvlMask &=
~(pvlOptInpNative | pvlOptInpString |
pvlOptOutNative | pvlOptOutString);
@@ -702,6 +706,7 @@ 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);
@@ -730,10 +735,13 @@ 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:
@@ -749,7 +757,7 @@ static void eventCallback(struct event_handler_args arg)
pca->sevr = pdbr_time_double->severity;
pca->stat = pdbr_time_double->status;
memcpy(&pca->timeStamp, &pdbr_time_double->stamp, sizeof(epicsTimeStamp));
if (precord) {
if (doScan && precord) {
struct pv_link *ppv_link = &plink->value.pv_link;
if ((ppv_link->pvlMask & pvlOptCP) ||
@@ -1006,7 +1014,8 @@ static void dbCaTask(void *arg)
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, 0);
pca->chid, eventCallback, pca, 0.0, 0.0, 0.0,
&pca->evidNative);
if (status != ECA_NORMAL) {
errlogPrintf("dbCaTask ca_add_array_event %s\n",
ca_message(status));
@@ -1018,7 +1027,8 @@ 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, 0);
pca->chid, eventCallback, pca, 0.0, 0.0, 0.0,
&pca->evidString);
if (status != ECA_NORMAL) {
errlogPrintf("dbCaTask ca_add_array_event %s\n",
ca_message(status));

View File

@@ -78,6 +78,8 @@ typedef struct caLink
char *pgetString;
void *pputNative;
char *pputString;
evid evidNative;
evid evidString;
char gotInNative;
char gotInString;
char gotOutNative;

View File

@@ -130,8 +130,8 @@ long dbcar(char *precordname, int level)
precord->name,
pdbFldDes->name,
plink->value.pv_link.pvname,
pca->nDisconnect,
pca->nNoWrite);
pca ? pca->nDisconnect : 0,
pca ? pca->nNoWrite : 0);
}
}
}

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.
\*************************************************************************/
/* dbConvert.c */
/*
@@ -582,7 +582,7 @@ static long getCharFloat(
}
return 0;
}
static long getCharDouble(
const dbAddr *paddr,
void *pto, long nRequest, long no_elements, long offset)
@@ -783,7 +783,7 @@ static long getUcharFloat(
}
return 0;
}
static long getUcharDouble(
const dbAddr *paddr,
void *pto, long nRequest, long no_elements, long offset)
@@ -984,7 +984,7 @@ static long getShortFloat(
}
return 0;
}
static long getShortDouble(
const dbAddr *paddr,
void *pto, long nRequest, long no_elements, long offset)
@@ -1184,7 +1184,7 @@ static long getUshortFloat(
}
return 0;
}
static long getUshortDouble(
const dbAddr *paddr,
void *pto, long nRequest, long no_elements, long offset)
@@ -1385,7 +1385,7 @@ static long getLongFloat(
}
return 0;
}
static long getLongDouble(
const dbAddr *paddr,
void *pto, long nRequest, long no_elements, long offset)
@@ -1586,7 +1586,7 @@ static long getUlongFloat(
}
return 0;
}
static long getUlongDouble(
const dbAddr *paddr,
void *pto, long nRequest, long no_elements, long offset)
@@ -1636,7 +1636,7 @@ static long getFloatString(
char *pbuffer = (char *) pto;
float *psrc = (float *) paddr->pfield;
long status = 0;
int precision = 6;
long precision = 6;
struct rset *prset = 0;
if (paddr) prset = dbGetRset(paddr);
@@ -1799,7 +1799,7 @@ static long getFloatFloat(
COPYNOCONVERT(sizeof(float), paddr->pfield, pto, nRequest, no_elements, offset);
return 0;
}
static long getFloatDouble(
const dbAddr *paddr,
void *pto, long nRequest, long no_elements, long offset)
@@ -1848,8 +1848,8 @@ static long getDoubleString(
{
char *pbuffer = (char *) pto;
double *psrc = (double *) paddr->pfield;
long status = 0;
int precision = 6;
long status = 0;
long precision = 6;
struct rset *prset = 0;
if (paddr) prset = dbGetRset(paddr);
@@ -2019,7 +2019,7 @@ static long getDoubleFloat(
}
return 0;
}
static long getDoubleDouble(
const dbAddr *paddr,
void *pto, long nRequest, long no_elements, long offset)
@@ -2217,7 +2217,7 @@ static long getEnumFloat(
}
return 0;
}
static long getEnumDouble(
const dbAddr *paddr,
void *pto, long nRequest, long no_elements, long offset)
@@ -2874,7 +2874,7 @@ static long putCharFloat(
}
return 0;
}
static long putCharDouble(
dbAddr *paddr,
const void *pfrom, long nRequest, long no_elements, long offset)
@@ -3077,7 +3077,7 @@ static long putUcharFloat(
}
return 0;
}
static long putUcharDouble(
dbAddr *paddr,
const void *pfrom, long nRequest, long no_elements, long offset)
@@ -3280,7 +3280,7 @@ static long putShortFloat(
}
return 0;
}
static long putShortDouble(
dbAddr *paddr,
const void *pfrom, long nRequest, long no_elements, long offset)
@@ -3483,7 +3483,7 @@ static long putUshortFloat(
}
return 0;
}
static long putUshortDouble(
dbAddr *paddr,
const void *pfrom, long nRequest, long no_elements, long offset)
@@ -3686,7 +3686,7 @@ static long putLongFloat(
}
return 0;
}
static long putLongDouble(
dbAddr *paddr,
const void *pfrom, long nRequest, long no_elements, long offset)
@@ -3889,7 +3889,7 @@ static long putUlongFloat(
}
return 0;
}
static long putUlongDouble(
dbAddr *paddr,
const void *pfrom, long nRequest, long no_elements, long offset)
@@ -3937,13 +3937,12 @@ static long putFloatString(
const void *pfrom, long nRequest, long no_elements, long offset)
{
const float *pbuffer = (const float *) pfrom;
char *pdest = (char *) paddr->pfield;
long status = 0;
int precision = 6;
struct rset *prset = 0;
char *pdest = (char *) paddr->pfield;
long status = 0;
long precision = 6;
struct rset *prset = dbGetRset(paddr);
short size = paddr->field_size;
if (paddr) prset = dbGetRset(paddr);
if (prset && (prset->get_precision))
status = (*prset->get_precision)(paddr,&precision);
if (nRequest==1 && offset==0) {
@@ -4103,7 +4102,7 @@ static long putFloatFloat(
COPYNOCONVERT(sizeof(float), pfrom, paddr->pfield, nRequest, no_elements, offset);
return 0;
}
static long putFloatDouble(
dbAddr *paddr,
const void *pfrom, long nRequest, long no_elements, long offset)
@@ -4151,13 +4150,12 @@ static long putDoubleString(
const void *pfrom, long nRequest, long no_elements, long offset)
{
const double *pbuffer = (const double *) pfrom;
char *pdest = (char *) paddr->pfield;
long status = 0;
int precision = 6;
struct rset *prset = 0;
char *pdest = (char *) paddr->pfield;
long status = 0;
long precision = 6;
struct rset *prset = dbGetRset(paddr);
short size = paddr->field_size;
if (paddr) prset = dbGetRset(paddr);
if (prset && (prset->get_precision))
status = (*prset->get_precision)(paddr,&precision);
if (nRequest==1 && offset==0) {
@@ -4324,7 +4322,7 @@ static long putDoubleFloat(
}
return 0;
}
static long putDoubleDouble(
dbAddr *paddr,
const void *pfrom, long nRequest, long no_elements, long offset)
@@ -4533,7 +4531,7 @@ static long putEnumFloat(
}
return 0;
}
static long putEnumDouble(
dbAddr *paddr,
const void *pfrom, long nRequest, long no_elements, long offset)

View File

@@ -117,6 +117,8 @@ static char *EVENT_PEND_NAME = "eventTask";
static struct evSubscrip canceledEvent;
static epicsMutexId stopSync;
static unsigned short ringSpace ( const struct event_que *pevq )
{
if ( pevq->evque[pevq->putix] == EVENTQEMPTY ) {
@@ -258,6 +260,10 @@ dbEventCtx db_init_events (void)
{
struct event_user * evUser;
if (!stopSync) {
stopSync = epicsMutexMustCreate();
}
if (!dbevEventUserFreeList) {
freeListInitPvt(&dbevEventUserFreeList,
sizeof(struct event_user),8);
@@ -321,6 +327,8 @@ fail:
return NULL;
}
/* intentionally leak stopSync to avoid possible shutdown races */
/*
* DB_CLOSE_EVENTS()
*
@@ -356,11 +364,15 @@ void db_close_events (dbEventCtx ctx)
epicsMutexUnlock ( evUser->lock );
epicsMutexMustLock (stopSync);
epicsEventDestroy(evUser->pexitsem);
epicsEventDestroy(evUser->ppendsem);
epicsEventDestroy(evUser->pflush_sem);
epicsMutexDestroy(evUser->lock);
epicsMutexUnlock (stopSync);
freeListFree(dbevEventUserFreeList, evUser);
}
@@ -1043,8 +1055,15 @@ static void event_task (void *pParm)
taskwdRemove(epicsThreadGetIdSelf());
/* use stopSync to ensure pexitsem is not destroy'd
* until epicsEventSignal() has returned.
*/
epicsMutexMustLock (stopSync);
epicsEventSignal(evUser->pexitsem);
epicsMutexUnlock(stopSync);
return;
}

View File

@@ -23,6 +23,7 @@
#include "cvtFast.h"
#include "dbDefs.h"
#include "ellLib.h"
#include "epicsStdlib.h"
#include "epicsThread.h"
#include "epicsTime.h"
#include "errlog.h"
@@ -96,6 +97,103 @@ static const char * link_field_name(const struct link *plink)
/***************************** Constant Links *****************************/
/* Convert functions */
/* The difference between these and dbFastConvert is that constants
* may contain hex numbers, whereas database conversions can't.
*/
/* Copy to STRING */
static long cvt_st_st(const char *from, void *pfield, const dbAddr *paddr)
{
char *to = pfield;
size_t size;
if (paddr && paddr->field_size < MAX_STRING_SIZE) {
size = paddr->field_size - 1;
} else {
size = MAX_STRING_SIZE - 1;
}
strncpy(to, from, size);
to[size] = 0;
return 0;
}
/* Most integer conversions are identical */
#define cvt_st_int(TYPE) static long \
cvt_st_ ## TYPE(const char *from, void *pfield, const dbAddr *paddr) { \
epics##TYPE *to = pfield; \
char *end; \
\
if (*from == 0) { \
*to = 0; \
return 0; \
} \
return epicsParse##TYPE(from, to, 0, &end); \
}
/* Instanciate for CHAR, UCHAR, SHORT, USHORT and LONG */
cvt_st_int(Int8)
cvt_st_int(UInt8)
cvt_st_int(Int16)
cvt_st_int(UInt16)
cvt_st_int(Int32)
/* Conversion for ULONG is different... */
static long cvt_st_UInt32(const char *from, void *pfield, const dbAddr *paddr)
{
epicsUInt32 *to = pfield;
char *end;
long status;
if (*from == 0) {
*to = 0;
return 0;
}
status = epicsParseUInt32(from, to, 0, &end);
if (status == S_stdlib_noConversion ||
(!status && (*end == '.' || *end == 'e' || *end == 'E'))) {
/*
* Convert via double so numbers like 1.0e3 convert properly.
* db_access pretends ULONG fields are DOUBLE.
*/
double dval;
status = epicsParseFloat64(from, &dval, &end);
if (!status &&
dval >=0 &&
dval <= ULONG_MAX)
*to = dval;
}
return status;
}
/* Float conversions are identical */
#define cvt_st_float(TYPE) static long \
cvt_st_ ## TYPE(const char *from, void *pfield, const dbAddr *paddr) { \
epics##TYPE *to = pfield; \
char *end; \
\
if (*from == 0) { \
*to = 0; \
return 0; \
} \
return epicsParse##TYPE(from, to, &end); \
}
/* Instanciate for FLOAT32 and FLOAT64 */
cvt_st_float(Float32)
cvt_st_float(Float64)
static long (*convert[DBF_DOUBLE+1])(const char *, void *, const dbAddr *) = {
cvt_st_st,
cvt_st_Int8, cvt_st_UInt8,
cvt_st_Int16, cvt_st_UInt16,
cvt_st_Int32, cvt_st_UInt32,
cvt_st_Float32, cvt_st_Float64
};
static long dbConstLoadLink(struct link *plink, short dbrType, void *pbuffer)
{
if (!plink->value.constantStr)
@@ -105,8 +203,7 @@ static long dbConstLoadLink(struct link *plink, short dbrType, void *pbuffer)
if (dbrType== DBF_MENU || dbrType == DBF_ENUM || dbrType == DBF_DEVICE)
dbrType = DBF_USHORT;
return dbFastPutConvertRoutine[DBR_STRING][dbrType]
(plink->value.constantStr, pbuffer, NULL);
return convert[dbrType](plink->value.constantStr, pbuffer, NULL);
}
static long dbConstGetNelements(const struct link *plink, long *nelements)
@@ -116,7 +213,7 @@ static long dbConstGetNelements(const struct link *plink, long *nelements)
}
static long dbConstGetLink(struct link *plink, short dbrType, void *pbuffer,
epicsEnum16 *pstat, epicsEnum16 *psevr, long *pnRequest)
long *pnRequest)
{
if (pnRequest)
*pnRequest = 0;
@@ -194,7 +291,7 @@ static long dbDbGetElements(const struct link *plink, long *nelements)
}
static long dbDbGetValue(struct link *plink, short dbrType, void *pbuffer,
epicsEnum16 *pstat, epicsEnum16 *psevr, long *pnRequest)
long *pnRequest)
{
struct pv_link *ppv_link = &plink->value.pv_link;
DBADDR *paddr = ppv_link->pvt;
@@ -211,8 +308,6 @@ static long dbDbGetValue(struct link *plink, short dbrType, void *pbuffer,
if (status)
return status;
}
*pstat = paddr->precord->stat;
*psevr = paddr->precord->sevr;
if (ppv_link->getCvt && ppv_link->lastGetdbrType == dbrType) {
status = ppv_link->getCvt(paddr->pfield, pbuffer, paddr);
@@ -233,6 +328,9 @@ static long dbDbGetValue(struct link *plink, short dbrType, void *pbuffer,
}
ppv_link->lastGetdbrType = dbrType;
}
if (!status && precord != paddr->precord)
inherit_severity(ppv_link, precord,
paddr->precord->stat, paddr->precord->sevr);
return status;
}
@@ -542,23 +640,22 @@ long dbGetLink(struct link *plink, short dbrType, void *pbuffer,
switch (plink->type) {
case CONSTANT:
status = dbConstGetLink(plink, dbrType, pbuffer, &stat, &sevr,
pnRequest);
status = dbConstGetLink(plink, dbrType, pbuffer, pnRequest);
break;
case DB_LINK:
status = dbDbGetValue(plink, dbrType, pbuffer, &stat, &sevr, pnRequest);
status = dbDbGetValue(plink, dbrType, pbuffer, pnRequest);
break;
case CA_LINK:
status = dbCaGetLink(plink, dbrType, pbuffer, &stat, &sevr, pnRequest);
if (!status)
inherit_severity(&plink->value.pv_link, precord, stat, sevr);
break;
default:
cantProceed("dbGetLinkValue: Illegal link type %d\n", plink->type);
printf("dbGetLinkValue: Illegal link type %d\n", plink->type);
status = -1;
}
if (status) {
recGblSetSevr(precord, LINK_ALARM, INVALID_ALARM);
} else {
inherit_severity(&plink->value.pv_link, precord, stat, sevr);
}
return status;
}
@@ -658,7 +755,7 @@ long dbPutLink(struct link *plink, short dbrType, const void *pbuffer,
status = dbCaPutLink(plink, dbrType, pbuffer, nRequest);
break;
default:
cantProceed("dbPutLinkValue: Illegal link type %d\n", plink->type);
printf("dbPutLinkValue: Illegal link type %d\n", plink->type);
status = -1;
}
if (status) {
@@ -739,4 +836,3 @@ long dbPutLinkLS(struct link *plink, char *pbuffer, epicsUInt32 len)
return dbPutLink(plink, DBR_STRING, pbuffer, 1);
}

View File

@@ -34,7 +34,7 @@ typedef struct lset {
int (*getDBFtype)(const struct link *plink);
long (*getElements)(const struct link *plink, long *nelements);
long (*getValue)(struct link *plink, short dbrType, void *pbuffer,
epicsEnum16 *pstat, epicsEnum16 *psevr, long *pnRequest);
long *pnRequest);
long (*getControlLimits)(const struct link *plink, double *lo, double *hi);
long (*getGraphicLimits)(const struct link *plink, double *lo, double *hi);
long (*getAlarmLimits)(const struct link *plink, double *lolo, double *lo,

View File

@@ -552,10 +552,10 @@ long dblsr(char *recordname,int level)
printf(" Not Locked\n");
} else {
printf(" thread %p",plockSet->thread_id);
if(! plockSet->precord || !plockSet->precord->name)
printf(" NULL record or record name\n");
if(! plockSet->precord)
printf(" NULL record\n");
else
printf(" record %s\n",plockSet->precord->name);
printf(" record %s\n",plockSet->precord->name);
}
if(level==0) { if(recordname) break; continue; }
for(plockRecord = (lockRecord *)ellFirst(&plockSet->lockRecordList);

View File

@@ -6,7 +6,7 @@
* Copyright (c) 2013 Helmholtz-Zentrum Berlin
* für Materialien und Energie GmbH.
* 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.
\*************************************************************************/
/* dbScan.c */
/* tasks and subroutines to scan the database */
@@ -111,8 +111,8 @@ static char *priorityName[NUM_CALLBACK_PRIORITIES] = {
typedef struct event_list {
CALLBACK callback[NUM_CALLBACK_PRIORITIES];
scan_list scan_list[NUM_CALLBACK_PRIORITIES];
struct event_list *next;
char event_name[MAX_STRING_SIZE];
struct event_list *next;
char eventname[1]; /* actually arbitrary size */
} event_list;
static event_list * volatile pevent_list[256];
static epicsMutexId event_lock;
@@ -161,8 +161,11 @@ void scanStop(void)
interruptAccept = FALSE;
for (i = 0; i < nPeriodic; i++) {
papPeriodic[i]->scanCtl = ctlExit;
epicsEventSignal(papPeriodic[i]->loopEvent);
periodic_scan_list *ppsl = papPeriodic[i];
if (!ppsl) continue;
ppsl->scanCtl = ctlExit;
epicsEventSignal(ppsl->loopEvent);
epicsEventWait(startStopEvent);
}
@@ -207,16 +210,24 @@ void scanRun(void)
interruptAccept = TRUE;
scanCtl = ctlRun;
for (i = 0; i < nPeriodic; i++)
papPeriodic[i]->scanCtl = ctlRun;
for (i = 0; i < nPeriodic; i++) {
periodic_scan_list *ppsl = papPeriodic[i];
if (!ppsl) continue;
ppsl->scanCtl = ctlRun;
}
}
void scanPause(void)
{
int i;
for (i = nPeriodic - 1; i >= 0; --i)
papPeriodic[i]->scanCtl = ctlPause;
for (i = nPeriodic - 1; i >= 0; --i) {
periodic_scan_list *ppsl = papPeriodic[i];
if (!ppsl) continue;
ppsl->scanCtl = ctlPause;
}
scanCtl = ctlPause;
interruptAccept = FALSE;
@@ -238,11 +249,6 @@ void scanAdd(struct dbCommon *precord)
event_list *pel;
eventname = precord->evnt;
if (strlen(eventname) >= MAX_STRING_SIZE) {
recGblRecordError(S_db_badField, (void *)precord,
"scanAdd: too long EVNT value");
return;
}
prio = precord->prio;
if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
recGblRecordError(-1, (void *)precord,
@@ -288,9 +294,11 @@ void scanAdd(struct dbCommon *precord)
}
addToList(precord, &piosh->iosl[prio].scan_list);
} else if (scan >= SCAN_1ST_PERIODIC) {
addToList(precord, &papPeriodic[scan - SCAN_1ST_PERIODIC]->scan_list);
periodic_scan_list *ppsl = papPeriodic[scan - SCAN_1ST_PERIODIC];
if (ppsl)
addToList(precord, &ppsl->scan_list);
}
return;
}
void scanDelete(struct dbCommon *precord)
@@ -304,24 +312,17 @@ void scanDelete(struct dbCommon *precord)
recGblRecordError(-1, (void *)precord,
"scanDelete detected illegal SCAN value");
} else if (scan == menuScanEvent) {
char* eventname;
int prio;
event_list *pel;
scan_list *psl = 0;
eventname = precord->evnt;
prio = precord->prio;
if (prio < 0 || prio >= NUM_CALLBACK_PRIORITIES) {
recGblRecordError(-1, (void *)precord,
"scanDelete detected illegal PRIO field");
return;
}
do /* multithreading: make sure pel is consistent */
pel = pevent_list[0];
while (pel != pevent_list[0]);
for (; pel; pel=pel->next) {
if (strcmp(pel->event_name, eventname) == 0) break;
}
pel = eventNameToHandle(precord->evnt);
if (pel && (psl = &pel->scan_list[prio]))
deleteFromList(precord, psl);
} else if (scan == menuScanI_O_Intr) {
@@ -354,28 +355,48 @@ void scanDelete(struct dbCommon *precord)
}
deleteFromList(precord, &piosh->iosl[prio].scan_list);
} else if (scan >= SCAN_1ST_PERIODIC) {
deleteFromList(precord, &papPeriodic[scan - SCAN_1ST_PERIODIC]->scan_list);
periodic_scan_list *ppsl = papPeriodic[scan - SCAN_1ST_PERIODIC];
if (ppsl)
deleteFromList(precord, &ppsl->scan_list);
}
return;
}
double scanPeriod(int scan) {
periodic_scan_list *ppsl;
scan -= SCAN_1ST_PERIODIC;
if (scan < 0 || scan >= nPeriodic)
return 0.0;
return papPeriodic[scan]->period;
ppsl = papPeriodic[scan];
return ppsl ? ppsl->period : 0.0;
}
int scanppl(double period) /* print periodic list */
int scanppl(double period) /* print periodic scan list(s) */
{
periodic_scan_list *ppsl;
dbMenu *pmenu = dbFindMenu(pdbbase, "menuScan");
char message[80];
int i;
if (!pmenu || !papPeriodic) {
printf("scanppl: dbScan subsystem not initialized\n");
return -1;
}
for (i = 0; i < nPeriodic; i++) {
ppsl = papPeriodic[i];
if (ppsl == NULL) continue;
if (period > 0.0 && (fabs(period - ppsl->period) >.05)) continue;
periodic_scan_list *ppsl = papPeriodic[i];
if (!ppsl) {
const char *choice = pmenu->papChoiceValue[i + SCAN_1ST_PERIODIC];
printf("Periodic scan list for SCAN = '%s' not initialized\n",
choice);
continue;
}
if (period > 0.0 &&
(fabs(period - ppsl->period) > 0.05))
continue;
sprintf(message, "Records with SCAN = '%s' (%lu over-runs):",
ppsl->name, ppsl->overruns);
printList(&ppsl->scan_list, message);
@@ -389,14 +410,12 @@ int scanpel(const char* eventname) /* print event list */
int prio;
event_list *pel;
do /* multithreading: make sure pel is consistent */
pel = pevent_list[0];
while (pel != pevent_list[0]);
for (; pel; pel = pel->next) {
if (!eventname || strcmp(pel->event_name, eventname) == 0) {
for (pel = pevent_list[0]; pel; pel = pel->next) {
if (!eventname || epicsStrGlobMatch(pel->eventname, eventname)) {
printf("Event \"%s\"\n", pel->eventname);
for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
if (ellCount(&pel->scan_list[prio].list) == 0) continue;
sprintf(message, "Event \"%s\" Priority %s", pel->event_name, priorityName[prio]);
sprintf(message, " Priority %s", priorityName[prio]);
printList(&pel->scan_list[prio], message);
}
}
@@ -447,18 +466,52 @@ event_list *eventNameToHandle(const char *eventname)
int prio;
event_list *pel;
static epicsThreadOnceId onceId = EPICS_THREAD_ONCE_INIT;
double eventnumber = 0;
size_t namelength;
if (!eventname || eventname[0] == 0)
return NULL;
if (!eventname) return NULL;
while (isspace((unsigned char)eventname[0])) eventname++;
if (!eventname[0]) return NULL;
namelength = strlen(eventname);
while (isspace((unsigned char)eventname[namelength-1])) namelength--;
/* Backward compatibility with numeric events:
Treat any string that represents a double with an
integer part between 0 and 255 the same as the integer
because it is most probably a conversion from double
like from a calc record.
*/
if (epicsParseDouble(eventname, &eventnumber, NULL) == 0)
{
if (eventnumber >= 0 && eventnumber < 256)
{
if (eventnumber < 1)
return NULL; /* 0 is no event */
if ((pel = pevent_list[(int)eventnumber]) != NULL)
return pel;
}
else
eventnumber = 0; /* not a numeric event between 1 and 255 */
}
epicsThreadOnce(&onceId, eventOnce, NULL);
epicsMutexMustLock(event_lock);
for (pel = pevent_list[0]; pel; pel=pel->next) {
if (strcmp(pel->event_name, eventname) == 0) break;
if (strncmp(pel->eventname, eventname, namelength) == 0
&& pel->eventname[namelength] == 0)
break;
}
if (pel == NULL) {
pel = dbCalloc(1, sizeof(event_list));
strcpy(pel->event_name, eventname);
pel = calloc(1, sizeof(event_list) + namelength);
if (!pel)
goto done;
if (eventnumber > 0) {
/* backward compatibility: make all numeric events look like integers */
sprintf(pel->eventname, "%i", (int)eventnumber);
pevent_list[(int)eventnumber] = pel;
}
else
strncpy(pel->eventname, eventname, namelength);
for (prio = 0; prio < NUM_CALLBACK_PRIORITIES; prio++) {
callbackSetUser(&pel->scan_list[prio], &pel->callback[prio]);
callbackSetPriority(prio, &pel->callback[prio]);
@@ -468,13 +521,8 @@ event_list *eventNameToHandle(const char *eventname)
}
pel->next=pevent_list[0];
pevent_list[0]=pel;
{ /* backward compatibility */
char* p;
long e = strtol(eventname, &p, 0);
if (*p == 0 && e > 0 && e <= 255)
pevent_list[e] = pel;
}
}
done:
epicsMutexUnlock(event_lock);
return pel;
}
@@ -494,13 +542,8 @@ void postEvent(event_list *pel)
/* backward compatibility */
void post_event(int event)
{
event_list* pel;
if (event <= 0 || event > 255) return;
do { /* multithreading: make sure pel is consistent */
pel = pevent_list[event];
} while (pel != pevent_list[event]);
postEvent(pel);
postEvent(pevent_list[event]);
}
static void ioscanOnce(void *arg)
@@ -694,7 +737,7 @@ static void periodicTask(void *arg)
if (++overruns >= 10 &&
epicsTimeDiffInSeconds(&now, &reported) > report_delay) {
errlogPrintf("\ndbScan warning from '%s' scan thread:\n"
"\tScan processing averages %.2f seconds (%.2f .. %.2f).\n"
"\tScan processing averages %.3f seconds (%.3f .. %.3f).\n"
"\tOver-runs have now happened %u times in a row.\n"
"\tTo fix this, move some records to a slower scan rate.\n",
ppsl->name, ppsl->period + overtime / overruns,
@@ -741,12 +784,8 @@ static void initPeriodic(void)
char *unit;
int status = epicsParseDouble(choice, &number, &unit);
ppsl->scan_list.lock = epicsMutexMustCreate();
ellInit(&ppsl->scan_list.list);
ppsl->name = choice;
if (status || number == 0) {
if (status || number <= 0) {
errlogPrintf("initPeriodic: Bad menuScan choice '%s'\n", choice);
ppsl->period = i;
}
else if (!*unit ||
!epicsStrCaseCmp(unit, "second") ||
@@ -767,16 +806,24 @@ static void initPeriodic(void)
}
else {
errlogPrintf("initPeriodic: Bad menuScan choice '%s'\n", choice);
ppsl->period = i;
}
if (ppsl->period == 0) {
free(ppsl);
continue;
}
ppsl->scan_list.lock = epicsMutexMustCreate();
ellInit(&ppsl->scan_list.list);
ppsl->name = choice;
ppsl->scanCtl = ctlPause;
ppsl->loopEvent = epicsEventMustCreate(epicsEventEmpty);
number = ppsl->period / quantum;
if ((ppsl->period < 2 * quantum) ||
(number / floor(number) > 1.1)) {
errlogPrintf("initPeriodic: Scan rate '%s' is not achievable.\n",
choice);
}
ppsl->scanCtl = ctlPause;
ppsl->loopEvent = epicsEventMustCreate(epicsEventEmpty);
papPeriodic[i] = ppsl;
}
@@ -788,6 +835,8 @@ static void deletePeriodic(void)
for (i = 0; i < nPeriodic; i++) {
periodic_scan_list *ppsl = papPeriodic[i];
if (!ppsl) continue;
ellFree(&ppsl->scan_list.list);
epicsEventDestroy(ppsl->loopEvent);
epicsMutexDestroy(ppsl->scan_list.lock);
@@ -800,10 +849,11 @@ static void deletePeriodic(void)
static void spawnPeriodic(int ind)
{
periodic_scan_list *ppsl;
periodic_scan_list *ppsl = papPeriodic[ind];
char taskName[20];
ppsl = papPeriodic[ind];
if (!ppsl) return;
sprintf(taskName, "scan-%g", ppsl->period);
periodicTaskId[ind] = epicsThreadCreate(
taskName, epicsThreadPriorityScanLow + ind,

View File

@@ -50,7 +50,7 @@ epicsShareFunc void scanCleanup(void);
epicsShareFunc EVENTPVT eventNameToHandle(const char* event);
epicsShareFunc void postEvent(EVENTPVT epvt);
epicsShareFunc void post_event(int event) EPICS_DEPRECATED;
epicsShareFunc void post_event(int event);
epicsShareFunc void scanAdd(struct dbCommon *);
epicsShareFunc void scanDelete(struct dbCommon *);
epicsShareFunc double scanPeriod(int scan);

View File

@@ -308,6 +308,11 @@ long dbgf(const char *pname)
if (nameToAddr(pname, &addr))
return -1;
if (addr.precord->lset == NULL) {
printf("dbgf only works after iocInit\n");
return -1;
}
no_elements = MIN(addr.no_elements, sizeof(buffer)/addr.field_size);
if (addr.dbr_field_type == DBR_ENUM) {
long status = dbGetField(&addr, DBR_STRING, pbuffer,
@@ -344,6 +349,11 @@ long dbpf(const char *pname,const char *pvalue)
if (nameToAddr(pname, &addr))
return -1;
if (addr.precord->lset == NULL) {
printf("dbpf only works after iocInit\n");
return -1;
}
if (addr.no_elements > 1 &&
(addr.dbr_field_type == DBR_CHAR || addr.dbr_field_type == DBR_UCHAR)) {
dbrType = addr.dbr_field_type;
@@ -398,6 +408,11 @@ long dbtr(const char *pname)
if (nameToAddr(pname, &addr))
return -1;
if (addr.precord->lset == NULL) {
printf("dbtr only works after iocInit\n");
return -1;
}
precord = (struct dbCommon*)addr.precord;
if (precord->pact) {
printf("record active\n");
@@ -437,6 +452,11 @@ long dbtgf(const char *pname)
if (nameToAddr(pname, &addr))
return -1;
if (addr.precord->lset == NULL) {
printf("dbtgf only works after iocInit\n");
return -1;
}
/* try all options first */
req_options = 0xffffffff;
ret_options = req_options;
@@ -534,6 +554,11 @@ long dbtpf(const char *pname, const char *pvalue)
if (nameToAddr(pname, &addr))
return -1;
if (addr.precord->lset == NULL) {
printf("dbtpf only works after iocInit\n");
return -1;
}
val_long = strtol(pvalue, &pend, 10);
validLong = (*pend == 0);
@@ -797,7 +822,7 @@ static void printBuffer(
printf("no_strs = %u:\n",
pdbr_enumStrs->no_str);
for (i = 0; i < pdbr_enumStrs->no_str; i++)
for (i = 0; i < pdbr_enumStrs->no_str; i++)
printf("\t\"%s\"\n", pdbr_enumStrs->strs[i]);
}
else {

View File

@@ -16,6 +16,7 @@
#include "epicsUnitTest.h"
#include "osiFileName.h"
#include "registry.h"
#include "epicsThread.h"
#define epicsExportSharedSymbols
#include "dbAccess.h"
@@ -111,7 +112,7 @@ long testdbVPutField(const char* pv, short dbrType, va_list ap)
return dbPutField(&addr, dbrType, pod.bytes, 1);
}
void testdbPutFieldOk(const char* pv, short dbrType, ...)
void testdbPutFieldOk(const char* pv, int dbrType, ...)
{
long ret;
va_list ap;
@@ -123,7 +124,7 @@ void testdbPutFieldOk(const char* pv, short dbrType, ...)
testOk(ret==0, "dbPutField(%s, %d, ...) == %ld", pv, dbrType, ret);
}
void testdbPutFieldFail(long status, const char* pv, short dbrType, ...)
void testdbPutFieldFail(long status, const char* pv, int dbrType, ...)
{
long ret;
va_list ap;
@@ -138,7 +139,7 @@ void testdbPutFieldFail(long status, const char* pv, short dbrType, ...)
testFail("dbPutField(\"%s\", %d, ...) != %ld (%ld)", pv, dbrType, status, ret);
}
void testdbGetFieldEqual(const char* pv, short dbrType, ...)
void testdbGetFieldEqual(const char* pv, int dbrType, ...)
{
va_list ap;
@@ -163,6 +164,9 @@ void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap)
if(status) {
testFail("dbGetField(\"%s\",%d,...) returns %ld", pv, dbrType, status);
return;
} else if(nReq==0) {
testFail("dbGetField(\"%s\", %d, ...) -> zero length", pv, dbrType);
return;
}
switch(dbrType) {
@@ -190,6 +194,72 @@ void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap)
}
}
void testdbGetArrFieldEqual(const char* pv, short dbfType, long nRequest, unsigned long cnt, const void *pbufraw)
{
DBADDR addr;
const long vSize = dbValueSize(dbfType);
const long nStore = vSize * nRequest;
long status;
char *gbuf, *gstore;
const char *pbuf = pbufraw;
if(dbNameToAddr(pv, &addr)) {
testFail("Missing PV \"%s\"", pv);
return;
}
gbuf = gstore = malloc(nStore);
if(!gbuf && nStore!=0) { /* note that malloc(0) is allowed to return NULL on success */
testFail("Allocation failed esize=%ld total=%ld", vSize, nStore);
return;
}
status = dbGetField(&addr, dbfType, gbuf, NULL, &nRequest, NULL);
if (status) {
testFail("dbGetField(\"%s\", %d, ...) -> %#lx", pv, dbfType, status);
} else {
unsigned match = nRequest==cnt;
long n, N = nRequest < cnt ? nRequest : cnt;
if(!match)
testDiag("Length mis-match. expected=%lu actual=%lu", cnt, nRequest);
for(n=0; n<N; n++, gbuf+=vSize, pbuf+=vSize) {
switch(dbfType) {
case DBR_STRING: {
const char *expect = (const char*)pbuf,
*actual = (const char*)gbuf;
/* expected (pbuf) is allowed to omit storage for trailing nils for last element */
unsigned int eq = strncmp(expect, actual, MAX_STRING_SIZE)==0 && actual[MAX_STRING_SIZE-1]=='\0';
match &= eq;
if(!eq)
testDiag("[%lu] = expected=\"%s\" actual=\"%s\"", n, expect, actual);
break;
}
#define OP(DBR,Type,pat) case DBR: {Type expect = *(Type*)pbuf, actual = *(Type*)gbuf; assert(vSize==sizeof(Type)); match &= expect==actual; \
if(expect!=actual) testDiag("[%lu] expected=" pat " actual=" pat, n, expect, actual); break;}
OP(DBR_CHAR, char, "%c");
OP(DBR_UCHAR, unsigned char, "%u");
OP(DBR_SHORT, short, "%d");
OP(DBR_USHORT, unsigned short, "%u");
OP(DBR_LONG, int, "%d");
OP(DBR_ULONG, unsigned int, "%u");
OP(DBR_FLOAT, float, "%e");
OP(DBR_DOUBLE, double, "%e");
OP(DBR_ENUM, int, "%d");
#undef OP
}
}
testOk(match, "dbGetField(\"%s\", dbrType=%d, nRequest=%ld ...) match", pv, dbfType, nRequest);
}
free(gstore);
}
dbCommon* testdbRecordPtr(const char* pv)
{
DBADDR addr;
@@ -199,3 +269,26 @@ dbCommon* testdbRecordPtr(const char* pv)
return addr.precord;
}
static
epicsMutexId test_global;
static
epicsThreadOnceId test_global_once = EPICS_THREAD_ONCE_INIT;
static
void test_global_init(void* ignored)
{
test_global = epicsMutexMustCreate();
}
void testGlobalLock(void)
{
epicsThreadOnce(&test_global_once, &test_global_init, NULL);
epicsMutexMustLock(test_global);
}
void testGlobalUnlock(void)
{
epicsMutexUnlock(test_global);
}

View File

@@ -46,17 +46,93 @@ epicsShareFunc void testdbCleanup(void);
* testdbPutFieldOk("pvname", DBF_FLOAT, (double)4.1);
* testdbPutFieldOk("pvname", DBF_STRING, "hello world");
*/
epicsShareFunc void testdbPutFieldOk(const char* pv, short dbrType, ...);
epicsShareFunc void testdbPutFieldOk(const char* pv, int dbrType, ...);
/* Tests for put failure */
epicsShareFunc void testdbPutFieldFail(long status, const char* pv, short dbrType, ...);
epicsShareFunc void testdbPutFieldFail(long status, const char* pv, int dbrType, ...);
epicsShareFunc long testdbVPutField(const char* pv, short dbrType, va_list ap);
epicsShareFunc void testdbGetFieldEqual(const char* pv, short dbrType, ...);
epicsShareFunc void testdbGetFieldEqual(const char* pv, int dbrType, ...);
epicsShareFunc void testdbVGetFieldEqual(const char* pv, short dbrType, va_list ap);
/**
* @param pv PV name string
* @param dbfType One of the DBF_* macros from dbAccess.h
* @param nRequest Number of elements to request from pv
* @param pbufcnt Number of elements pointed to be pbuf
* @param pbuf Expected value buffer
*
* Execute dbGet() of nRequest elements and compare the result with
* pbuf (pbufcnt is an element count).
* Element size is derived from dbfType.
*
* nRequest > pbufcnt will detect truncation.
* nRequest < pbufcnt always fails.
* nRequest ==pbufcnt checks prefix (actual may be longer than expected)
*/
epicsShareFunc void testdbGetArrFieldEqual(const char* pv, short dbfType, long nRequest, unsigned long pbufcnt, const void *pbuf);
epicsShareFunc dbCommon* testdbRecordPtr(const char* pv);
/** Synchronize the shared callback queues.
*
* Block until all callback queue jobs which were queued, or running,
* have completed.
*/
epicsShareFunc void testSyncCallback(void);
/** Global mutex for use by test code.
*
* This utility mutex is intended to be used to avoid races in situations
* where some other syncronization primitive is being destroyed (epicsEvent,
* epicsMutex, ...).
*
* For example. The following has a subtle race where the event may be
* destroyed (free()'d) before the call to epicsEventMustSignal() has
* returned. On some targets this leads to a use after free() error.
*
@code
epicsEventId evt;
void thread1() {
evt = epicsEventMustCreate(...);
// spawn thread2()
epicsEventMustWait(evt);
epicsEventDestroy(evt);
}
// ...
void thread2() {
epicsEventMustSignal(evt);
}
@endcode
*
* One way to avoid this race is to use a global mutex to ensure
* that epicsEventMustSignal() has returned before destroying
* the event.
*
@code
epicsEventId evt;
void thread1() {
evt = epicsEventMustCreate(...);
// spawn thread2()
epicsEventMustWait(evt);
testGlobalLock(); // <-- added
epicsEventDestroy(evt);
testGlobalUnlock(); // <-- added
}
// ...
void thread2() {
testGlobalLock(); // <-- added
epicsEventMustSignal(evt);
testGlobalUnlock(); // <-- added
}
@endcode
*
* This must be a global mutex to avoid simply shifting the race
* from the event to a locally allocated mutex.
*/
epicsShareFunc void testGlobalLock(void);
epicsShareFunc void testGlobalUnlock(void);
#ifdef __cplusplus
}
#endif

View File

@@ -172,6 +172,7 @@ int pft(const char *pname, const char *pvalue)
ca_dump_dbr(DBR_ENUM,1, buffer);
}
printf("\n");
dbChannelDelete(chan);
return (0);
}
@@ -231,6 +232,7 @@ int tpn(const char *pname, const char *pvalue)
ppn = calloc(1, sizeof(processNotify));
if (!ppn) {
printf("calloc failed\n");
dbChannelDelete(chan);
return -1;
}
ppn->requestType = putProcessRequest;
@@ -241,6 +243,8 @@ int tpn(const char *pname, const char *pvalue)
ptpnInfo = calloc(1, sizeof(tpnInfo));
if (!ptpnInfo) {
printf("calloc failed\n");
free(ppn);
dbChannelDelete(chan);
return -1;
}
ptpnInfo->ppn = ppn;

View File

@@ -18,6 +18,7 @@
#include <limits.h>
#include "dbDefs.h"
#include "alarm.h"
#include "epicsMath.h"
#include "epicsPrint.h"
#include "epicsStdlib.h"
@@ -181,6 +182,9 @@ unsigned short recGblResetAlarms(void *precord)
epicsEnum16 val_mask = 0;
epicsEnum16 stat_mask = 0;
if (new_sevr > INVALID_ALARM)
new_sevr = INVALID_ALARM;
pdbc->stat = new_stat;
pdbc->sevr = new_sevr;
pdbc->nsta = 0;

View File

@@ -131,7 +131,14 @@ recGblCheckDeadbandTest_SRCS += dbTestIoc_registerRecordDeviceDriver.cpp
testHarness_SRCS += recGblCheckDeadbandTest.c
TESTS += recGblCheckDeadbandTest
# The testHarness runs all the test programs in a known working order.
TESTPROD_HOST += testPutGetTest
testPutGetTest_SRCS += dbPutGetTest.c
testPutGetTest_SRCS += dbTestIoc_registerRecordDeviceDriver.cpp
testHarness_SRCS += dbPutGetTest.db
TESTFILES += ../dbPutGetTest.db
TESTS += testPutGetTest
# This runs all the test programs in a known working order:
testHarness_SRCS += epicsRunDbTests.c
dbTestHarness_SRCS += $(testHarness_SRCS)

View File

@@ -34,6 +34,8 @@
*
* Two time intervals are measured. The time to queue and run each of
* the immediate callbacks, and the actual delay of the delayed callback.
*
* Slow callbacks no longer fail the test, they just emit a diagnostic.
*/
#define NCALLBACKS 169
@@ -108,7 +110,7 @@ MAIN(callbackParallelTest)
for (j = 0; j < 5; j++)
setupError[i][j] = timeError[i][j] = defaultError[j];
testPlan(4);
testPlan(2);
testDiag("Starting %d parallel callback threads", noCpus);
@@ -165,7 +167,8 @@ MAIN(callbackParallelTest)
}
}
testOk(faults == 0, "%d faults during callback setup", faults);
testOk(slowups <= 1, "%d slowups during callback setup", slowups);
if (slowups)
testDiag("%d slowups during callback setup", slowups);
slowups = 0;
for (i = 0; i < NCALLBACKS ; i++) {
@@ -182,7 +185,8 @@ MAIN(callbackParallelTest)
}
updateStats(timeError[i%NUM_CALLBACK_PRIORITIES], error);
}
testOk(slowups < 5, "%d slowups during callbacks", slowups);
if (slowups)
testDiag("%d slowups during callback setup", slowups);
testDiag("Setup time statistics");
printStats(setupError[0], "LOW");

View File

@@ -34,6 +34,8 @@
*
* Two time intervals are measured. The time to queue and run each of
* the immediate callbacks, and the actual delay of the delayed callback.
*
* Slow callbacks no longer fail the test, they just emit a diagnostic.
*/
#define NCALLBACKS 169
@@ -108,7 +110,7 @@ MAIN(callbackTest)
for (j = 0; j < 5; j++)
setupError[i][j] = timeError[i][j] = defaultError[j];
testPlan(4);
testPlan(2);
callbackInit();
epicsThreadSleep(1.0);
@@ -162,7 +164,8 @@ MAIN(callbackTest)
}
}
testOk(faults == 0, "%d faults during callback setup", faults);
testOk(slowups <= 1, "%d slowups during callback setup", slowups);
if (slowups)
testDiag("%d slowups during callback setup", slowups);
slowups = 0;
for (i = 0; i < NCALLBACKS ; i++) {
@@ -179,7 +182,8 @@ MAIN(callbackTest)
}
updateStats(timeError[i%NUM_CALLBACK_PRIORITIES], error);
}
testOk(slowups < 5, "%d slowups during callbacks", slowups);
if (slowups)
testDiag("%d slowups during callback setup", slowups);
testDiag("Setup time statistics");
printStats(setupError[0], "LOW");

View File

@@ -541,8 +541,11 @@ MAIN(chfPluginTest)
dbChannel *pch;
db_field_log *pfl;
#if defined(WIN32) && (!defined(_MINGW) || __MSVCRT_VERSION__ >= 0x0800)
#ifdef _WIN32
#if (defined(_MSC_VER) && _MSC_VER < 1900) || \
(defined(_MINGW) && defined(_TWO_DIGIT_EXPONENT))
_set_output_format(_TWO_DIGIT_EXPONENT);
#endif
#endif
testPlan(1433);

View File

@@ -0,0 +1,150 @@
#include <string.h>
#include <errlog.h>
#include <dbAccess.h>
#include <dbStaticLib.h>
#include <dbStaticPvt.h>
#include <dbUnitTest.h>
#include <testMain.h>
static
void testdbGetStringEqual(const char *pv, const char *expected)
{
const char *actual;
int ok;
DBENTRY ent;
dbInitEntry(pdbbase, &ent);
if(dbFindRecord(&ent, pv)) {
testFail("Failed to find record '%s'", pv);
return;
}
actual = dbGetString(&ent);
ok = (!actual && !expected)
|| (actual && expected && strcmp(actual, expected)==0);
testOk(ok, "dbGetString(\"%s\") -> \"%s\" == \"%s\"", pv, actual, expected);
dbFinishEntry(&ent);
}
static
void testGetString(void)
{
testDiag("testGetString()");
testdbGetStringEqual("recempty.DTYP", "Soft Channel");
testdbGetStringEqual("recempty.DESC", "");
testdbGetStringEqual("recempty.PHAS", "0");
testdbGetStringEqual("recempty.TSE" , "0");
testdbGetStringEqual("recempty.DISA", "0");
testdbGetStringEqual("recempty.DISV", "0");
testdbGetStringEqual("recoverwrite.DTYP", "Soft Channel");
testdbGetStringEqual("recoverwrite.DESC", "");
testdbGetStringEqual("recoverwrite.PHAS", "0");
testdbGetStringEqual("recoverwrite.TSE" , "0");
testdbGetStringEqual("recoverwrite.DISA", "0");
testdbGetStringEqual("recoverwrite.DISV", "0");
}
static
void testStringMax(void)
{
testDiag("testStringMax()");
testdbGetStringEqual("recmax.DISA", "-1");
}
static
void testLongLink(void)
{
testDiag("testLonkLink()");
testdbGetFieldEqual("lnktest.INP", DBR_STRING, "lnktarget NPP NMS");
testdbGetFieldEqual("lnktest.INP$", DBR_STRING, "lnktarget NPP NMS");
testDiag("dbGet() w/ nRequest==1 gets only trailing nil");
testdbGetFieldEqual("lnktest.INP$", DBR_CHAR, '\0');
testdbGetArrFieldEqual("lnktest.INP$", DBR_CHAR, 19, 18, "lnktarget NPP NMS");
testDiag("get w/ truncation");
testdbGetArrFieldEqual("lnktest.INP$", DBR_CHAR, 0, 0, NULL);
testdbGetArrFieldEqual("lnktest.INP$", DBR_CHAR, 1, 1, "");
testdbGetArrFieldEqual("lnktest.INP$", DBR_CHAR, 2, 2, "l");
testdbGetArrFieldEqual("lnktest.INP$", DBR_CHAR, 3, 3, "ln");
testdbGetArrFieldEqual("lnktest.INP$", DBR_CHAR, 17, 17, "lnktarget NPP NM");
testdbGetArrFieldEqual("lnktest.INP$", DBR_CHAR, 18, 18, "lnktarget NPP NMS");
testdbGetArrFieldEqual("lnktest.INP", DBR_STRING, 2, 1, "lnktarget NPP NMS");
}
static
void testLongAttr(void)
{
testDiag("testLongAttr()");
testdbGetFieldEqual("lnktest.RTYP", DBR_STRING, "x");
testdbGetFieldEqual("lnktest.RTYP$", DBR_STRING, "x");
testDiag("dbGet() w/ nRequest==1 gets only trailing nil");
testdbGetFieldEqual("lnktest.RTYP$", DBR_CHAR, '\0');
testdbGetArrFieldEqual("lnktest.RTYP$", DBR_CHAR, 4, 2, "x");
testDiag("get w/ truncation");
testdbGetArrFieldEqual("lnktest.RTYP$", DBR_CHAR, 0, 0, NULL);
testdbGetArrFieldEqual("lnktest.RTYP$", DBR_CHAR, 1, 1, "");
testdbGetArrFieldEqual("lnktest.RTYP$", DBR_CHAR, 2, 2, "x");
}
static
void testLongField(void)
{
testDiag("testLongField()");
testdbGetFieldEqual("lnktest.NAME", DBR_STRING, "lnktest");
testdbGetFieldEqual("lnktest.NAME$", DBR_STRING, "108");
testDiag("dbGet() w/ nRequest==1 gets only trailing nil");
testdbGetFieldEqual("lnktest.NAME$", DBR_CHAR, '\0');
testdbGetArrFieldEqual("lnktest.NAME$", DBR_CHAR, 10, 8, "lnktest");
testDiag("get w/ truncation");
testdbGetArrFieldEqual("lnktest.NAME$", DBR_CHAR, 0, 0, NULL);
testdbGetArrFieldEqual("lnktest.NAME$", DBR_CHAR, 1, 1, "");
testdbGetArrFieldEqual("lnktest.NAME$", DBR_CHAR, 2, 2, "l");
testdbGetArrFieldEqual("lnktest.NAME$", DBR_CHAR, 3, 3, "ln");
testdbGetArrFieldEqual("lnktest.NAME$", DBR_CHAR, 7, 7, "lnktes");
testdbGetArrFieldEqual("lnktest.NAME$", DBR_CHAR, 8, 8, "lnktest");
}
void dbTestIoc_registerRecordDeviceDriver(struct dbBase *);
MAIN(dbPutGet)
{
testPlan(41);
testdbPrepare();
testdbReadDatabase("dbTestIoc.dbd", NULL, NULL);
dbTestIoc_registerRecordDeviceDriver(pdbbase);
testdbReadDatabase("dbPutGetTest.db", NULL, NULL);
testGetString();
testStringMax();
eltc(0);
testIocInitOk();
eltc(1);
testLongLink();
testLongAttr();
testLongField();
testIocShutdownOk();
testdbCleanup();
return testDone();
}

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