Compare commits

...

237 Commits

Author SHA1 Message Date
Ralph Lange
65574b5971 Update CONFIG_BASE_VERSION for 3.15.4, remove "not released" from RELEASE_NOTES 2016-05-27 08:54:04 +02:00
Andrew Johnson
4284222b54 Convert GUI_ promptgroup strings to new-style 2016-05-26 16:15:48 +02:00
Ralph Lange
54bab1e2f0 pcas: fix compiler warning (gcc 5.3.1) 2016-05-26 14:14:56 +02:00
Andrew Johnson
df200de27f Fix lsi/lso puts with DBF_STRING data 2016-05-26 13:49:18 +02:00
Ralph Lange
22d6ebe7e1 Merge changes from 3.14 branch up to rev 12642 2016-05-26 13:18:38 +02:00
Ralph Lange
9c3ed1bfe2 catools: fix escape handling when sending long strings 2016-05-26 13:13:29 +02:00
Ralph Lange
23fd4e202b ca: Fix client bug (race condition) in ipAddrToAsciiEngine 2016-05-25 12:26:32 +02:00
Andrew Johnson
a5b8b0b890 Use fabs() in calcPerform 2016-05-24 11:12:25 +02:00
Andrew Johnson
988614ae8a Reset SNAPSHOT after -rc1 tagged 2016-05-22 06:06:53 +02:00
Ralph Lange
fe887b4f83 Update CONFIG_BASE_VERSION for 3.15.4-rc1 2016-05-20 16:37:06 +02:00
Andrew Johnson
7be7ad2768 Merge changes from 3.14 branch, to revno 12640 2016-05-18 10:44:16 -05:00
Andrew Johnson
6c9555310a Update EPICS_TIMEZONE with info for 2016-2021 2016-05-18 10:26:04 -05:00
Andrew Johnson
4ccc2e9d3a Merged my devEnviron branch 2016-05-18 09:48:22 -05:00
Andrew Johnson
122fb6c731 New "getenv" device support for string input types 2016-05-17 19:09:48 -05:00
Andrew Johnson
3b8fd13152 libCom: NTP Time Provider adjusts to OS tick rate changes
Allow the NTP Time provider (used on VxWorks and RTEMS only)
to adapt to changes in the OS clock tick rate after the provider
has been initialized.

Changing the tick rate after iocInit() is not advisable,
other software might still misbehave if initialized before
an OS tick rate change.

Back-ported from the 3.15 branch (commit 12468).
2016-05-17 16:03:27 -05:00
Andrew Johnson
04a9fdb4e3 Clean up warnings from gcc 5.2 2016-05-16 17:02:34 -05:00
Andrew Johnson
3c61880d79 Allow some callback slow-ups before failing tests
The tests occasionally fail on Windows because the server
is busy; this will accept up to 4 slow callbacks without
them causing the build to fail.
2016-05-16 16:55:50 -05:00
Andrew Johnson
8081d3ada4 Merged Till's fix for lp:1581212, modified 2016-05-13 14:48:08 -05:00
Andrew Johnson
6d35ee9c3c Move dbLock.h *after* epicsExportSharedSymbols 2016-05-13 13:40:37 -05:00
Andrew Johnson
b5a0657adc Applied Till's fix for lp:1581212 2016-05-13 13:30:55 -05:00
Andrew Johnson
b87f3eaaee Merged changes from 3.14 branch to revno 12636 2016-05-13 13:12:08 -05:00
Andrew Johnson
6db0e13809 Added CROSS_COMPILER_RUNTEST_ARCHS 2016-05-13 13:00:48 -05:00
Michael Davidsaver
0f6c997288 osdNetIntf: ignore 0.0.0.0 as a broadcast address
It seems in some situations Linux (at least)
sets IFF_BROADCAST bug leaves the bcast address
set to 0.0.0.0.

Fixes lp:1581505
2016-05-13 09:31:26 -04:00
Michael Davidsaver
704c748fbd Revert "libCom/osi: osiSockDiscoverBroadcastAddresses() finds 127.255.255.255"
This reverts commit e805abe971.
2016-05-13 09:14:20 -04:00
Andrew Johnson
82456f83ee Fix Menu declaration test 2016-05-12 16:35:54 -05:00
Andrew Johnson
e98a6bbafa Make <menu>_NUM_CHOICES not an enum tag
Fixes lp:1580972
2016-05-12 15:05:18 -05:00
Andrew Johnson
9b51444fb7 Fix data types and macro name 2016-05-04 18:15:54 -05:00
Andrew Johnson
3be97865b3 Warn instead of building cap5 if xsubpp is missing 2016-05-04 14:41:51 -05:00
Andrew Johnson
67097456e3 Add additional RELEASE file checks
These checks are important for mixing Debian modules with
privately-built applications.
2016-05-03 12:26:40 -05:00
Andrew Johnson
3c8af4c571 Catch bad attribute names/values to prevent a segfault 2016-05-02 11:38:51 -05:00
Michael Davidsaver
26c04844cf add test for lp:1577108 2016-05-01 13:30:45 -04:00
Michael Davidsaver
a3d981ad0a dbLink.c: fix dbGetLink for array of length 1 2016-05-01 13:30:45 -04:00
Ralph Lange
924aa2f93b Set Base version to -pre1-DEV 2016-04-29 12:20:35 +02:00
Ralph Lange
457fb8fa13 Update CONFIG_BASE_VERSION for 3.15.4-pre1 2016-04-29 11:34:05 +02:00
Ralph Lange
b8b259de6f Merge Andrew's libs-prereq branch 2016-04-29 10:42:03 +02:00
Andrew Johnson
7ce8e5ea01 Fix RTEMS Makefile issue 2016-04-28 23:59:39 -05:00
Andrew Johnson
496414c88c Fix for VxWorks 5.5 compiler 2016-04-28 23:28:39 -05:00
Andrew Johnson
2acde8bac7 Merged changes from 3.14 branch to revno 12630 2016-04-28 21:39:55 -05:00
Andrew Johnson
2c69ddbee5 Merged my ioc-arch branch, manually re-based 2016-04-28 19:26:11 -05:00
Andrew Johnson
ba0d5f9443 Disallow single-quoted strings in Perl DBD parser 2016-04-28 19:03:17 -05:00
Andrew Johnson
08fd987c60 Perl script clean-up 2016-04-28 19:00:37 -05:00
Andrew Johnson
5a605fa0c3 Set various EPICS_VERSION_* environment variables
These are set at the same time as the ARCH variable.
Had to add EPICS_VERSION_SHORT and EPICS_VERSION_FULL to epicsVersion.h.

This uses more uniform names, should we change epicsVersion.h names?
We would continue to support the old names in parallel for some time.
2016-04-28 18:58:07 -05:00
Andrew Johnson
0e5dc2a21c More build parameters.
Renamed EPICS_TARGET_ARCH to EPICS_BUILD_TARGET_ARCH
Added EPICS_BUILD_OS_CLASS and EPICS_BUILD_COMPILER_CLASS
2016-04-28 18:56:03 -05:00
Andrew Johnson
230603f4ac Remove ARCH from cdCommands and envPaths files
Set it in iocshRegisterCommon() instead.
Remove ARCH from iocBoot/ioc/Makefile@Common templates.
2016-04-28 18:50:41 -05:00
Andrew Johnson
396ff3c484 Add EPICS_TARGET_ARCH parameter
Set its default value automatically in the generated envData.c
2016-04-28 18:49:10 -05:00
Andrew Johnson
09fbeaf6d3 Merged Ralph's new-promptgroups branch 2016-04-28 18:27:15 -05:00
Andrew Johnson
b4a8a1ac98 Fix dbFreeBase() issue causing segfaults 2016-04-28 18:10:26 -05:00
Andrew Johnson
ee87aecd6e Always have linker search INSTALL_LIB 2016-04-28 14:32:21 -05:00
Andrew Johnson
054a234c70 Parentheses in macro 2016-04-28 13:27:47 -05:00
Andrew Johnson
24ddcd2524 Fix epicsTimeZoneTest.cpp => .c and remove conditional 2016-04-27 12:09:10 -05:00
Michael Davidsaver
2226f3acb9 libCom/test: don't include epicsTimeZoneTest for vxWorks 2016-04-27 12:45:18 -04:00
Andrew Johnson
f0f89b4b1c Fix file paths in comments 2016-04-27 10:28:57 -05:00
Andrew Johnson
fdda079b8f BSD's finite expects a double; make glibc 2.23 happy 2016-04-27 10:28:01 -05:00
Ralph Lange
1f36670175 dbStatic: remove obsolete GUIGROUPS_GBLSOURCE definition 2016-04-27 09:14:51 +02:00
Andrew Johnson
1ede873200 Fixed some space/tab issues in DBD files 2016-04-26 16:20:12 -05:00
Michael Davidsaver
51dd371784 rsrv: add rsrvCS_shutdown to avoid race in destroyAllChannels()
A race can occur between rsrv and cac by way of asLib
whereby casAccessRightsCB() is called after
a channel_in_use has been removed from
chanList/chanPendingUpdateARList.
casAccessRightsCB() would then attempt to remove
the node again, causing corruption.

Create a new rsrvCS_shutdown state when the
channel is not in either list.

Attempt to resolve lp:1571224
2016-04-26 17:06:22 -04:00
Andrew Johnson
72745d7b0c Only make runtests and tapfiles if T_A = EPICS_HOST_ARCH 2016-04-29 16:20:25 -05:00
Andrew Johnson
c933d77963 Add rule to install libraries before linking executables
The rule must be disabled for building libCom and gdd though.
2016-04-26 15:18:31 -05:00
Michael Davidsaver
93597e20d5 add epicsTimeZoneTest to libCom test harness 2016-04-26 09:59:22 -04:00
Michael Davidsaver
f0453faf36 libCom/test: add test for HST time zone
Test US/Hawaii zone which does not observe daylight saving time.
2016-04-26 09:28:09 -04:00
Ralph Lange
473992cfb9 Update release notes 2016-04-26 13:47:12 +02:00
Ralph Lange
6a362f467d rec: implement new promptgroup (gui_group) choices 2016-04-26 13:28:28 +02:00
Andrew Johnson
af07e0fd51 Fix oops in last commit 2016-04-25 12:24:05 -05:00
Andrew Johnson
de38b80795 Apply partial solution for Windows builds of Cap5 2016-04-25 11:54:17 -05:00
Ralph Lange
7bb27ad3e7 dbStatic: deprecate guigroup.h; remove from includes 2016-04-22 17:02:21 +02:00
Ralph Lange
1e1799c30e tools: change RE to allow any value for promptgroup in the Perl DBD parser 2016-04-18 09:56:41 +02:00
Andrew Johnson
8358580190 Merged commit 12623 from 3.14 branch. 2016-04-15 17:38:41 -05:00
Andrew Johnson
24e39b252d Print RTEMS version at startup 2016-04-15 17:37:07 -05:00
Ralph Lange
ce7044c711 dbStatic: collect promptgroup enum choices when reading dbd 2016-04-06 15:38:35 +02:00
Andrew Johnson
177090e35e Merged fixes for lp:1558206 and lp:1563191 from 3.14 branch, revno 12622 2016-03-30 11:26:53 -05:00
Andrew Johnson
430da57a35 Release notes for lp:1563191 2016-03-30 11:00:48 -05:00
Andrew Johnson
d2d637d0c2 Prevent string overflow in recGblInitConstantLink() 2016-03-29 12:04:08 -05:00
Michael Davidsaver
106fae3b26 dbStatic: prevent overflow in dbPutString()
The bounds check should be before the string
copy.  Also zero the last element out of
paranoia (should already be zero).

Fix lp:1563191
2016-03-29 17:36:39 +09:00
Andrew Johnson
3179e65791 Clean-up after lp:1558206 fix 2016-03-16 18:15:14 -05:00
Michael Davidsaver
6b9bfb09a5 pWaitRelease in wrong place
waitRelease==false indicates that pThread
has not be delete'd
2016-03-16 17:43:52 -04:00
Michael Davidsaver
4e312b9f64 libCom: exitWait() from thread exit handler corrupts stack
The epicsThreadCallEntryPoint() function stores a pointer
to a local variable in epicsThread::pWaitReleaseFlag.
Calling epicsAtThreadExit::exitWait() from that thread's
epicsAtThreadExit() handler writes to this pointer
after epicsThreadCallEntryPoint() has returned.
Thus corrupting the stack.

Set pWaitReleaseFlag=NULL before return to prevent this.

fixes lp:1558206
2016-03-16 14:40:37 -04:00
Andrew Johnson
59fea64390 Add missing dependencies for Test.dbd files 2016-03-16 13:10:17 -05:00
Andrew Johnson
f260124733 Ensure mbb* MASK calculated properly 2016-03-10 13:05:00 -06:00
Andrew Johnson
bd2ada3f8c Reformat Release Notes slightly 2016-03-03 16:02:46 -06:00
Andrew Johnson
113076a009 Allow quotes in DBD argument strings 2016-03-03 11:19:22 -06:00
Andrew Johnson
9502841b55 Silence unused variable warning 2016-03-02 10:41:34 -06:00
Andrew Johnson
b4404c8266 Clean up Release Notes merge 2016-02-29 17:53:59 -06:00
Andrew Johnson
f73f3332fa Merge RTEMS NTP fix from 3.14 branch, to revno 12615 2016-02-29 17:49:08 -06:00
Andrew Johnson
3f4c6abb31 Fix for RTEMS NTP sync issue 2016-02-29 17:07:03 -06:00
Andrew Johnson
76c422c5fd Merge Cygwin fix from 3.14, fix in rsrv too 2016-02-26 17:10:35 -06:00
Andrew Johnson
fee62836cd Use OS __CYGWIN__ macro, deprecate our CYGWIN32 2016-02-26 16:27:13 -06:00
Michael Davidsaver
2c48bcc26b dbChannelShow reporting detail level changed 2016-02-26 16:07:47 -05:00
Andrew Johnson
a3ab342833 Fix Release Notes for last commit 2016-02-26 14:22:00 -06:00
Andrew Johnson
3304470323 Merged the rsrvbindiface branch 2016-02-26 14:15:22 -06:00
Andrew Johnson
4f2f910d09 Added extern "C" wrappers to clean up some Solaris warnings 2016-02-26 13:50:39 -06:00
Andrew Johnson
217f515985 Merged fix-dbGet-arrays branch 2016-02-26 12:29:20 -06:00
Andrew Johnson
ebc59a4223 Add epicsAtomicTest to epicsRunLibComTests 2016-02-26 12:27:33 -06:00
Andrew Johnson
58285501de Revert, test programs may be included in harness without being run 2016-02-26 12:25:59 -06:00
Andrew Johnson
fa07bc3efe Added build files for cygwin to cross-compile linux-arm targets
Slightly strange combination and not actually tested, but could
be useful for some developers -- some FPGA tool-sets come with a
Cygwin cross-build environment for their target devices.
2016-02-26 11:19:37 -06:00
Michael Davidsaver
bfa8e324f7 remove dbChArrTest from testHarness
dbChArrTest calls iocInit() and so can't
be in the shared test harness
2016-02-25 21:10:42 -05:00
Michael Davidsaver
51a69862e7 ioc/db: single return for dbGet()
Single return path after call to prset->get_array_info
to ensure that paddr->pfield is restored.
2016-02-25 20:59:10 -05:00
Michael Davidsaver
4b8c11aeef memset transposed arguments 2016-02-25 20:08:44 -05:00
Andrew Johnson
62efa2e96a Fix the dbGet() array with field-log bug.
This also fixes a problem where the array is used in circular buffer
mode and the request has an offset, but the array is not actually
full at the time; to copy the data out of the array the convert()
routine needs to know the capacity of the array to know when to wrap
around, but we were passing it the current length instead.
2016-02-25 17:50:33 -06:00
Andrew Johnson
c7bcb09540 Add tests for dbGet() with db_field_log
Regression testing for a bug where an array field with a sub-array
channel filter can read past the end of the db_field_log array,
because in dbGet() the call to prset->get_array_info() occurs even
when pfl is supposed to be overriding the record's array.
2016-02-25 17:44:45 -06:00
Andrew Johnson
5ee778b0c2 Merged changes from Base-3.14, to revno 12613 2016-02-25 14:13:40 -06:00
Michael Davidsaver
7b3a040b34 rsrv: use SOCKERRNO
Must use OSI SOCKERRNO for correct handling
of errors w/ winsock
2016-02-25 11:32:56 -05:00
Andrew Johnson
e721be4ff5 Merged the posix-mlockall branch 2016-02-25 10:20:56 -06:00
Michael Davidsaver
88b47c021c cygwin inherits winsock broadcast behavior 2016-02-25 11:10:28 -05:00
Michael Davidsaver
d0a316f7ca win32: include ws2tcpip.h from osdSock.h
Needed to get some additional definitions
including IP_ADD_MEMBERSHIP
2016-02-25 11:02:09 -05:00
Ralph Lange
ba307ba6e7 rsrv: populate the server list - also on Windows builds 2016-02-25 09:36:31 +01:00
Andrew Johnson
d943f6966f Minor updates to the extensions/configure template 2016-02-24 17:39:29 -06:00
Andrew Johnson
76d7ce1f76 Fix MSVC (de)-optimizer issue 2016-02-24 15:06:59 -06:00
Andrew Johnson
66b0acbe3e Report UDP client status on Windows 2016-02-24 11:07:33 -06:00
Ralph Lange
822c6815c5 pcas: fix compilation on MSC Windows 2016-02-24 11:24:17 +01:00
Andrew Johnson
684ae7b35c Merged the fix-calc-bit-manipulation branch 2016-02-23 16:21:38 -06:00
Andrew Johnson
e18eca80db Changes from patch in lp:1539791 2016-02-23 15:43:26 -06:00
Andrew Johnson
b45622ac5e Test each bitwise cast individually for overflow 2016-02-23 12:42:00 -06:00
Andrew Johnson
89e6fdbca0 Fixed conversion overflows in tests
Minor tidying-up, added comments about casting for bitwise operations.
2016-02-19 15:57:44 -06:00
Ralph Lange
599e6635fb libCom/calc: fix bit31 bit manipulations 2016-02-18 15:19:01 +01:00
Ralph Lange
4241b4e6cb libCom/test: add calc tests for bit31 operators (lp:1514520) 2016-02-18 15:17:52 +01:00
Ralph Lange
9eedf0581e libCom/calc: Use epics(U)Int32 for all integer calculations
Adapted backport of 3.15 revision 12308
2016-02-18 14:44:43 +01:00
Michael Davidsaver
ffb23a3480 pcas: don't send beacons w/ connect()d socket
use sendto() and leave the origin field to 0.0.0.0
so it will be filled in by the receiving repeater
2016-02-16 16:28:04 -05:00
Andrew Johnson
61e61aab24 Use MS' strto[u]ll() if present 2016-02-12 15:15:19 -06:00
Andrew Johnson
d3e046a466 Document [s:e] and [s] filter usage 2016-02-12 14:20:33 -06:00
Andrew Johnson
99d331e50a Print timestamp with bad UDP msg errors 2016-02-11 14:36:48 -06:00
Andrew Johnson
9d95528eba Show UDP name server status in casr 2+ output 2016-02-08 16:34:37 -06:00
Michael Davidsaver
95a1998e0b update release notes 2016-02-04 19:09:44 -05:00
Michael Davidsaver
5769db3862 rsrv: "casr 1" shows ignore list 2016-02-04 18:57:02 -05:00
Michael Davidsaver
00a74fbb4e libCom: fix debug print formats in osiSockDiscoverBroadcastAddresses() 2016-02-04 18:45:18 -05:00
Michael Davidsaver
03fde89dd4 rsrv: EPICS_CAS_IGNORE_ADDR_LIST 2016-02-04 18:44:33 -05:00
Michael Davidsaver
8421b46398 update release notes 2016-02-04 17:59:08 -05:00
Michael Davidsaver
650aaea203 ca: update CAref.html with changes to beacon address list
Note that server beacon address list will no longer
consider client address list as a fallback.
2016-02-04 17:56:31 -05:00
Michael Davidsaver
fcfe7ed312 pcas: no fallbacks for beacon address list
Don't mix client and server configuration
by defaulting the server beacon list to use
the client address list.
2016-02-04 17:39:28 -05:00
Andrew Johnson
f2c4b2c81e Add config for linux cross-compile to windows-x64-mingw 2016-02-04 15:57:23 -06:00
Michael Davidsaver
167dea3735 rsrv: decouple some client/server config
the automatic beacon address list should follow
the server interface address list, and not be
effected by any client config.

Also, don't populate the interface address list
from EPICS_CAS_BEACON_ADDR_LIST as this will
almost never contain local interface addresses.
2016-01-29 08:33:41 -05:00
Andrew Johnson
1c1eb030a9 Improve casr() output 2016-01-27 17:59:38 -06:00
Andrew Johnson
43cf5af621 dbQuietMacroWarnings control 2016-01-26 12:28:00 -06:00
Michael Davidsaver
235e4bd835 rsrv: more beacon address fixups
should really be based on *server* config
as beacons should be sent to clients attempting
to connect to the server.

By default send beacons to bcast addresses
from the interface address list.
2016-01-23 16:15:17 -05:00
Michael Davidsaver
601d6d9fe8 rsrv: oops
improper rebase
2016-01-23 13:53:44 -05:00
Michael Davidsaver
b961b25151 rsrv: fix wildcard check ordering
filter out mcast addresses before wildcard uniqueness check.
2016-01-23 13:53:44 -05:00
Michael Davidsaver
eb9246e4c9 rsrv: beaconCounter not updated 2016-01-21 17:14:23 -05:00
Andrew Johnson
d729006908 Fix build for vxWorks 5.5.2 (again) 2016-01-21 12:27:01 -06:00
Michael Davidsaver
0aeba281be update release notes 2016-01-21 13:05:56 -05:00
Michael Davidsaver
04fee51795 ipAddrToAsciiAsync.: don't try to join the daemon thread
This isn't really necessary and may unnecessarily delay
things (~10 sec. on Linux) if a query to an unreachable
DNS server is in progress.
2016-01-21 13:00:50 -05:00
Michael Davidsaver
cba449d53b pcas: listen for mcast search request 2016-01-21 12:17:02 -05:00
Michael Davidsaver
cdffcbfbae update release notes 2016-01-21 12:17:02 -05:00
Michael Davidsaver
ba5ea5da93 don't use EPICS_CA_ADDR_LIST for server interface list
keep existing behavior, and server binds wildcard
when only client address list is specified.
2016-01-21 12:17:02 -05:00
Michael Davidsaver
c884175a86 rsrv: loopback mcast beacons 2016-01-21 12:17:02 -05:00
Michael Davidsaver
a4e9dcff00 rsrv: fixup beacon address list handling
should be based on client interface list,
not server.
2016-01-21 12:17:02 -05:00
Michael Davidsaver
c9323da5e3 minor
fix typo
expand error message
skip redundant (and misleading) print of beacon address list
2016-01-21 12:17:02 -05:00
Andrew Johnson
ffe441d032 Fix build for vxWorks 5.5.2 2016-01-21 10:34:32 -06:00
Ralph Lange
45c8a173f3 libCom/osi: fix timespec definition for MinGW 2016-01-13 17:28:23 +01:00
Michael Davidsaver
98504d1cdc libca: enable mcast loopback 2016-01-11 20:59:08 -05:00
Michael Davidsaver
568ece9c27 rsrv: multicast name lookup 2016-01-11 20:59:08 -05:00
Michael Davidsaver
f876bdb42c rsrv: don't leak sockets when building tcp set 2016-01-11 20:59:08 -05:00
Michael Davidsaver
605074a580 rsrv: additional fallback for interface list 2016-01-11 20:59:08 -05:00
Michael Davidsaver
64da181e6f expand beacon address list when binding to wildcard 2016-01-11 20:59:08 -05:00
Michael Davidsaver
823613fb4f libca: addAddrToChannelAccessAddressList report success 2016-01-11 20:59:08 -05:00
Michael Davidsaver
f837add8c4 envDefs: add envGetBoolConfigParam 2016-01-11 20:59:08 -05:00
Michael Davidsaver
15307c4db6 rsrv: redo initialization to support bind multiple interfaces.
consolidate most setup tasks in rsrv_init(),
which now spawns threads directly.
For each interface create 3-4 sockets,

* TCP listener
* UDP receiver (unicast)
* UDP receiver (broadcast optional)
* UDP beacon sender
2016-01-11 20:59:07 -05:00
Michael Davidsaver
8d5815ac95 rsrv: move some from req_server to rsrv_init 2016-01-11 20:59:07 -05:00
Michael Davidsaver
25d7d46e08 rsrv: no lazy init of BUCKET 2016-01-11 20:59:07 -05:00
Michael Davidsaver
5f31d9d2b1 rsrv: unglobalize IOC_sock 2016-01-11 20:59:07 -05:00
Michael Davidsaver
bb67c9db2f rsrv: UDP listener on more than one iface 2016-01-11 20:59:07 -05:00
Michael Davidsaver
cb965611ce rsrv: casr show multiple UDP clients 2016-01-11 20:59:07 -05:00
Michael Davidsaver
e805abe971 libCom/osi: osiSockDiscoverBroadcastAddresses() finds 127.255.255.255
For the default implementation of osiSockDiscoverBroadcastAddresses()
allow the loopback interface to have IFF_BROADCAST set (usually isn't)
and on Linux assume that the loopback broadcast address is usable
even if IFF_BROADCAST isn't set.
2016-01-11 20:59:07 -05:00
Michael Davidsaver
c80f71e294 rsrv: more renaming 2016-01-11 20:59:07 -05:00
Michael Davidsaver
692bbafffe rsrv: placeholder for cast_server thread shutdown 2016-01-11 20:59:07 -05:00
Michael Davidsaver
fd863738be rename prsrv_cast_client in cast_server() 2016-01-11 20:59:07 -05:00
Michael Davidsaver
2052062324 remove global prsrv_cast_client 2016-01-11 20:59:07 -05:00
Michael Davidsaver
5d74216017 rsrv: unnecessary use of global 2016-01-11 20:59:07 -05:00
Michael Davidsaver
991ff308e0 rsrv: when binding to a specific interface also bind to iface bcast
An oddness of BSD sockets (not winsock) is that binding to
INADDR_ANY will receive unicast and broadcast, but binding to
a specific interface address receives only unicast.  The trick
is to bind a second socket to the interface broadcast address,
which will then receive only broadcasts.
2016-01-11 20:59:07 -05:00
Michael Davidsaver
77a5f0db77 epicsMMIODef.h use static inline
'static inline' is necessary for consistent behavior with C and C++.
Plain 'inline' in C can result in multiply defined symbol
errors when linking.
2016-01-05 21:31:51 -05:00
Bjorklund, Eric A
8d6469957e vxWorks: missing extern "C" around sysPci* prototypes 2016-01-05 21:16:04 -05:00
Andrew Johnson
ef90d2d3c7 Merged Michael's tzwin32 branch 2016-01-05 17:17:58 -06:00
Michael Davidsaver
2d9c529f5e osdTime: win32 use C89 localtime/gmtime
as recommended by Freddie Akeroyd
2015-12-21 11:15:04 -05:00
Michael Davidsaver
05d3dbf453 add epicsTimeZoneTest 2015-12-21 11:13:36 -05:00
Andrew Johnson
695f516cbf Fix softIoc build with space in path to Base
Also improved error messages from makeInstallDir.pl.
2015-12-10 13:26:21 -06:00
Ralph Lange
fda3824ab4 Set version back to -DEV, add "not released" to RELEASE_NOTES 2015-11-22 18:10:40 +01:00
Ralph Lange
42a67524e0 Update CONFIG_BASE_VERSION for 3.15.3, remove "not released" from RELEASE_NOTES 2015-11-22 17:54:12 +01:00
Ralph Lange
d4ed70154b doc: add reference to LP bug #1466129 to known problems page 2015-11-22 17:33:58 +01:00
Andrew Johnson
f776f6b422 Set Base version to -rc1-DEV 2015-10-26 14:31:25 -05:00
Ralph Lange
cd746a339f configure: update CONFIG_BASE_VERSION for 3.15.3-rc1 2015-10-26 17:22:37 +01:00
Ralph Lange
6438750615 tools: change builtin _USER_ macro name to avoid clashes with makeBaseApp 2015-10-26 13:41:46 +01:00
Andrew Johnson
2ec5c80652 Fix internal anchor in filters.pod 2015-10-13 18:39:50 -05:00
Andrew Johnson
e1039bacfc Merged DB file parser fix from 3.14, revno 12605 2015-10-13 14:41:39 -05:00
Andrew Johnson
54381b7bf9 Fix DB file parser crashes 2015-10-13 12:03:32 -05:00
Andrew Johnson
69d3c94328 Set Base version to -pre1-DEV 2015-10-12 10:38:00 -05:00
Ralph Lange
a02860728e configure: update CONFIG_BASE_VERSION for 3.15.3-pre1 2015-10-12 10:35:30 +02:00
Ralph Lange
440ccc3c4a Merged Andrew's ntptime-on-vxworks branch 2015-10-11 12:04:16 +02:00
Ralph Lange
3d19f19d81 Merge Ralph's config-from-snippets branch 2015-10-11 09:59:39 +02:00
Andrew Johnson
214edd42d1 Minor RULES_EXPAND changes
Added support for a _PATTERN variable which calls $(wildcard) and
prepends .. and the other SRC_DIRS automatically.
Use $(ECHO) instead of @echo so make -s works silently.
Added another meta-rule to create .d files when make needs one.
2015-10-11 00:50:50 -05:00
Ralph Lange
f8b0b2f5f0 tools: add new builtin macros to assemblies 2015-10-10 19:12:11 +02:00
Ralph Lange
8596dc41f2 configure: add assemblies to RULES_EXPAND 2015-10-10 18:55:17 +02:00
Ralph Lange
88cb33a04d tools: fix in assembleSnippets script and test for Windows (getpwuid() not implemented) 2015-10-10 18:54:20 +02:00
Ralph Lange
5af0663058 Back out 12706 (assembly integration in build system) 2015-10-10 18:17:35 +02:00
Ralph Lange
830704021d Add creating config files from snippets to build system. 2015-10-09 17:28:46 +02:00
Ralph Lange
96ee2cd00c tools: install assembleSnippets.pl 2015-10-09 15:28:40 +02:00
Ralph Lange
c2d2f671bb tools: add -M option to assembleSnippets.pl (creates dependency file) 2015-10-09 14:15:26 +02:00
Ralph Lange
4b9958304d tools: add assembleSnippets.pl and test 2015-10-09 11:25:45 +02:00
Andrew Johnson
d0875f4f12 Make the NTPTime provider optional on VxWorks 2015-10-05 17:44:26 -05:00
Andrew Johnson
c74eb27474 Merged changes from 3.14 branch, to revno 12604 2015-09-18 11:51:51 -05:00
Ralph Lange
5aa145920d rec: fix promptgroups for biRecord 2015-09-16 13:56:52 +02:00
Andrew Johnson
bc3cbd990f Applied Ambroz Bizjak's freeListItemsAvail.patch 2015-08-31 12:11:30 -05:00
Andrew Johnson
53bf7cd994 Applied Ambroz Bizjak's epicsSingletonMutex.patch 2015-08-31 11:54:04 -05:00
Andrew Johnson
a9c4d59537 Applied Ambroz Bizjak's timerQueueActive.patch 2015-08-31 11:52:32 -05:00
Robert Soliday
d32332d545 libCom/test: Fix for MSVS 2015 2015-08-27 11:34:41 -05:00
Andrew Johnson
88864e949b Merge changes from 3.14 branch, to revno 12599 2015-08-20 11:14:01 -05:00
Andrew Johnson
fe4f607e63 libCom/errlog: Don't store stderr in pvtData.console
Some VxWorks BSPs close the stderr stream that the shell running
the startup script created and open a new one for the interactive
shell. This change makes pvtData.console==NULL mean use stderr
instead of storing the stderr value in pvtData.console at init.
2015-08-13 10:44:52 -05:00
Andrew Johnson
9e82a96700 dbTest: Remove special ENUM handling from dbpf()
This was preventing the value check in cvt_st_menu() from working.
2015-08-10 15:04:11 -05:00
Andrew Johnson
ef7399159c dbAccess: Make dbPut() always do special processing after put
If the value gets rejected by a put to SCAN, we must still call
dbPutSpecial() to add the record back onto its old scan thread.
2015-08-10 15:03:48 -05:00
Andrew Johnson
d7b3293ba3 libCom: Use MSVC's struct timespec when available 2015-08-07 09:41:48 -05:00
Andrew Johnson
9014ca899d dbStatic: Fix invalid memory read 2015-07-30 11:57:50 -05:00
Andrew Johnson
c5130468cd Let dbdToHtml work with wrong newlines 2015-07-24 10:42:09 -05:00
Andrew Johnson
7dd067e887 Merged dbCa bug-fix from 3.14 branch, revno 12595 2015-07-23 18:02:54 -05:00
Andrew Johnson
c56091978c db: Fixed obscure dbCa bug
This could be triggered if dbCaRemoveLink() is called on a link for
which there is an outstanding dbCaPutCallback().

Normally a dbCaPutCallback() callback routine is passed the associated
userPvt pointer as an argument, but in the event that dbCaRemoveLink()
gets used on the same link between the put and its completion callback,
the callback routine was being called with the link pointer as the
argument instead.

For all the existing Asyn Soft Channel device supports this is not a
problem as they all pass the link pointer as their userPvt argument, but
that won't necessarily always be the case.

Also updated the comments describing the process of removing links.
2015-07-23 17:57:30 -05:00
Andrew Johnson
2f8e6bf17e Fix smoothing for Nan/Inf values in devAiSoftCallback 2015-07-23 13:05:38 -05:00
Andrew Johnson
144281e0a3 Removed extraneous .db file 2015-07-23 12:34:05 -05:00
Andrew Johnson
83c2414ad0 Merged changes from 3.14 branch to revno 12594 2015-07-23 10:13:07 -05:00
Michael Davidsaver
504665bf09 iocInit: move dbCaShutdown earlier
Switch dbCaShutdown from an exit hook to
be called from iocShutdown.  Place it
after callback shutdown.
2015-07-21 19:08:07 -04:00
Michael Davidsaver
1411522a11 dbCa: only add dbCaExit once 2015-07-21 15:53:37 -04:00
Andrew Johnson
ae3d3904d9 Fix minor locking issue in dbEvent.c 2015-07-17 18:09:14 -05:00
Andrew Johnson
002bafdf07 Add testHarnessDone 2015-07-17 18:06:58 -05:00
Michael Davidsaver
8bfa40d858 dbScan: avoid race on shutdown 2015-07-16 17:05:41 -04:00
Michael Davidsaver
138e2f1ad5 callback: fix race on shutdown
epicsEventDestory() in the main thread could be called
before epicsEventTrigger() completes in the worker.
2015-07-16 17:05:41 -04:00
Michael Davidsaver
fefe6fd1fc Fix shutdown issues with scan and callback.
The main reason for this merge proposal is the change to "public" API functions.

Use atomic counter to resolve data race on threadsRunning in callback.

Split up callbackShutdown() and scanShutdown() into two phases *Stop() and
*Cleanup(). The *Stop() functions signal worker threads, and wait for them to
exit. The *Cleanup() functions actually reclaim global resources.

These two mechanisms have couplings which are quite complex. I/O Intr scans
involve both scan lists and callbacks.
2015-07-16 11:48:29 -05:00
Andrew Johnson
5eb49ebaf0 Merged changes from 3.14 branch to revno 12590 2015-07-13 13:05:33 -05:00
Andrew Johnson
625172419e libCom: Make epicsReadline behave the same on Darwin 2015-07-01 12:00:42 -05:00
Andrew Johnson
80343363a4 configure: Include RULES_FILE_TYPE earlier
From Benjamin Franksen:

There is one remaining problem with the order of includes in the build
rules for 3.14.12.5: configure/RULES_BUILD includes RULES_FILE_TYPE
(which in turn includes the cfg/RULES* from modules in the RELEASE file)
*after* including RULES.Db and RULES_JAVA. This makes it impossible to
override (pattern) rules in one of these files. Instead,
$(CONFIG)/RULES_FILE_TYPE should be included first.
2015-07-01 11:30:02 -05:00
Andrew Johnson
444b89f557 libCom: Make readline support clean up on epicsExit() 2015-06-30 14:08:32 -05:00
Andrew Johnson
fa1ddeeb1b Removed the last vestiges of RSET::get_value() 2015-06-23 18:04:33 -05:00
Andrew Johnson
ca46bf70b7 Fixes to attribute handling in dbStaticLib
From Peter Leban of i-tech (Libera)
2015-06-23 17:06:54 -05:00
Andrew Johnson
c0e2a44365 Register dbPutAttribute with iocsh 2015-06-23 17:04:37 -05:00
Andrew Johnson
84c3ec7c64 db: Correct DBF_CHAR range in recGbl.c
Seems invisible, but spotted by Lawrence T. Prevatte III.
2015-06-23 15:51:00 -05:00
Andrew Johnson
65e781d58a db: Fix off-by-one error in initHookName()
Thanks to Lawrence T. Prevatte III for noticing that.
2015-06-23 14:46:29 -05:00
Andrew Johnson
a613a96ad3 libCom: Fix routine name in error message 2015-06-18 10:56:43 -05:00
Ralph Lange
fbd2d4dd31 dbStatic: fix buffer overrun in printing functions by extending the local buffer accordingly 2015-06-05 11:10:10 +02:00
Andrew Johnson
2c28d4b69e Merged Lewis Muir's CAref ToC update
Also added some entries for a couple of missing ca_sg routines.
2015-05-15 10:41:19 -05:00
Andrew Johnson
9946681f72 Update version numbers in documentation for 3.15.3 2015-05-15 10:06:06 -05:00
Ralph Lange
196baac7da documentation: put back red "not released yet" header to RELEASE_NOTES 2015-05-15 14:05:59 +02:00
Ralph Lange
ce93142fe1 configure: set version snapshot back to -DEV 2015-05-15 13:50:14 +02:00
J. Lewis Muir
5d61a512d1 doc: add ca_put_callback to CA ref man func call interface index
The ca_put_callback function is not listed in the CA Reference Manual's
function call interface index; add it.
2015-05-14 16:23:23 -05:00
215 changed files with 4921 additions and 2664 deletions

View File

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

View File

@@ -118,6 +118,13 @@ 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
# 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.
#
CROSS_COMPILER_RUNTEST_ARCHS=
# Build shared libraries (DLLs on Windows).
# Must be either YES or NO. Definitions in the target-specific
# os/CONFIG.Common.<target> and os/CONFIG_SITE.Common.<target> files may

View File

@@ -30,10 +30,8 @@
# 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 2015: EPICS_TIMEZONE=CST/CDT::360:030802:110102
# e.g. for ANL in 2016: EPICS_TIMEZONE=CST/CDT::360:031302:110602
#
# DST for 2015 US: Mar 08 - Nov 01
# EU: Mar 29 - Oct 25
# DST for 2016 US: Mar 13 - Nov 06
# EU: Mar 27 - Oct 30
# DST for 2017 US: Mar 12 - Nov 05
@@ -42,11 +40,15 @@
# EU: Mar 25 - Oct 28
# DST for 2019 US: Mar 10 - Nov 03
# EU: Mar 31 - Oct 27
# (see: http://www.timeanddate.com/time/map/)
# DST for 2020 US: Mar 08 - Nov 01
# EU: Mar 29 - Oct 25
# DST for 2021 US: Mar 14 - Nov 07
# EU: Mar 28 - Oct 31
# (see: http://www.timeanddate.com/time/dst/2016.html etc. )
#
# These values are for 2015:
EPICS_TIMEZONE=CST/CDT::360:030802:110102
#EPICS_TIMEZONE=CET/CEST::-60:032902:102502
# These values are for 2016:
EPICS_TIMEZONE=CST/CDT::360:031302:110602
#EPICS_TIMEZONE=CET/CEST::-60:032702:103002
# EPICS_TS_NTP_INET
# NTP time server ip address. Uses boot host if not set.

View File

@@ -24,11 +24,15 @@ else
clean$(DIVIDER)$(ARCH) clean:
endif
cdCommands envPaths dllPath.bat relPaths.sh: \
cdCommands dllPath.bat relPaths.sh: \
$(wildcard $(TOP)/configure/RELEASE*) \
$(wildcard $(TOP)/configure/CONFIG_SITE*) $(INSTALL_BIN)
$(wildcard $(TOP)/configure/CONFIG_SITE*) | $(INSTALL_BIN)
$(CONVERTRELEASE) -a $(ARCH) -t $(IOCS_APPL_TOP) $@
envPaths: $(wildcard $(TOP)/configure/RELEASE*) \
$(wildcard $(TOP)/configure/CONFIG_SITE*) | $(INSTALL_BIN)
$(CONVERTRELEASE) -t $(IOCS_APPL_TOP) $@
realclean:
$(RM) cdCommands envPaths dllPath.bat relPaths.sh

View File

@@ -81,6 +81,8 @@ else
host:
endif
-include $(CONFIG)/RULES_FILE_TYPE
-include $(CONFIG)/RULES.Db
#---------------------------------------------------------------
@@ -122,8 +124,6 @@ LIBTARGETS += $(LIBNAME) $(INSTALL_LIBS) $(TESTLIBNAME) \
$(LOADABLE_SHRLIBNAME) $(INSTALL_LOADABLE_SHRLIBS)
-include $(CONFIG)/RULES_FILE_TYPE
# Main targets
install: buildInstall
@@ -170,7 +170,13 @@ endif
$(DIRECTORY_TARGETS) :
$(MKDIR) -p $@
$(PRODNAME): $(INSTALL_LIB_INSTALLS)
# Install LIB_INSTALLS libraries before linking executables
$(TESTPRODNAME) $(PRODNAME): | $(INSTALL_LIB_INSTALLS)
# Install built libraries too, unless Makefile says to wait
ifneq ($(DELAY_INSTALL_LIBS),YES)
$(TESTPRODNAME) $(PRODNAME): | $(INSTALL_LIBS) $(INSTALL_DLLSTUB_LIBS)
endif
# RELEASE file consistency checking
checkRelease:
@@ -319,7 +325,9 @@ $(MODNAME): %$(MODEXT): %$(EXE)
# Automated testing
runtests: $(TESTSCRIPTS)
ifneq (,$(findstring $(T_A),$(EPICS_HOST_ARCH) $(CROSS_COMPILER_RUNTEST_ARCHS)))
-$(PERL) -MTest::Harness -e 'runtests @ARGV if @ARGV;' $^
endif
testspec: $(TESTSCRIPTS)
@$(RM) $@
@@ -333,7 +341,9 @@ tapfiles: $(TESTSCRIPTS) $(TAPFILES)
# A .tap file is the output from running the associated test script
%.tap: %.t
ifneq (,$(findstring $(T_A),$(EPICS_HOST_ARCH) $(CROSS_COMPILER_RUNTEST_ARCHS)))
-$(PERL) $< -tap > $@
endif
# If there's a perl test script (.plt) available, use it
%.t: ../%.plt

View File

@@ -2,6 +2,9 @@
vpath %@ $(USR_VPATH) $(ALL_SRC_DIRS)
#---------------------------------------------------------------
# Variable expansion
# Default settings
EXPAND_TOOL ?= $(PERL) $(TOOLS)/expandVars.pl
@@ -24,3 +27,39 @@ expand_clean:
@$(RM) $(EXPANDED)
.PHONY : expand_clean
#---------------------------------------------------------------
# Assemblies (files assembled from snippets)
ASSEMBLE_TOOL ?= $(PERL) $(TOOLS)/assembleSnippets.pl
define COMMON_ASSEMBLY_template
$1_SNIPPETS += $$(foreach dir, .. $$(SRC_DIRS), \
$$(wildcard $$(dir)/$$($1_PATTERN)))
$(COMMON_DIR)/$1: $$($1_SNIPPETS)
$(ECHO) "Assembling common file $$@ from snippets"
@$(RM) $1
$(ASSEMBLE_TOOL) -o $1 $$^
@$(MV) $1 $$@
endef
$(foreach asy, $(COMMON_ASSEMBLIES), \
$(eval $(call COMMON_ASSEMBLY_template,$(strip $(asy)))))
define ASSEMBLY_template
$1_SNIPPETS += $$(foreach dir, .. $$(SRC_DIRS), \
$$(wildcard $$(dir)/$$($1_PATTERN)))
$1: $$($1_SNIPPETS)
$(ECHO) "Assembling file $$@ from snippets"
@$(RM) $$@
$(ASSEMBLE_TOOL) -o $$@ $$^
endef
$(foreach asy, $(ASSEMBLIES), \
$(eval $(call ASSEMBLY_template,$(strip $(asy)))))
define ASSEMBLY_DEP_template
$1$(DEP):
@echo $1: > $$@
endef
$(foreach asy, $(sort $(COMMON_ASSEMBLIES) $(ASSEMBLIES)), \
$(eval $(call ASSEMBLY_DEP_template,$(strip $(asy)))))

View File

@@ -57,7 +57,7 @@ SHRLIB_LDLIBS = $(addprefix -l, $($*_LDLIBS) $(LIB_LIBS) $(USR_LIBS)) \
$(LDLIBS)
SHRLIB_DEPLIB_DIRS = $(foreach word, \
$(sort $(dir $($*_DEPLIBS) $(SHRLIB_DEPLIBS))), \
$(sort $(INSTALL_LIB)/ $(dir $($*_DEPLIBS) $(SHRLIB_DEPLIBS))), \
$(shell $(FULLPATHNAME) $(word)))
SHRLIBDIR_LDFLAGS += $(SHRLIB_DEPLIB_DIRS:%=-L%)
@@ -86,7 +86,7 @@ PROD_LDLIBS += $($(firstword $(LDLIBS_STATIC_$(STATIC_BUILD)) \
$(LDLIBS_SHARED_$(SHARED_LIBRARIES))))
PROD_DEPLIB_DIRS = $(foreach word, \
$(sort $(dir $($*_DEPLIBS) $(PROD_DEPLIBS))), \
$(sort $(INSTALL_LIB)/ $(dir $($*_DEPLIBS) $(PROD_DEPLIBS))), \
$(shell $(FULLPATHNAME) $(word)))
PRODDIR_LDFLAGS += $(PROD_DEPLIB_DIRS:%=-L%)

View File

@@ -26,14 +26,14 @@ POSIX_LDLIBS += -lpthread
ARCH_DEP_CFLAGS += -m32
ARCH_DEP_LDFLAGS += -m32
# Compiler defines _X86_ 1
# Compiler defines __MSVCRT__ 1
# 32-bit compiler defines _X86_ 1
# Compiler defines __CYGWIN__ 1
# Compiler defines __CYGWIN32__ 1
# 32-bit compiler defines __CYGWIN32__ 1
# Compiler defines __unix__ 1
# Compiler defines __unix 1
# Compiler defines unix 1
# This macro now deprecated, use __CYGWIN__ in the future
OP_SYS_CPPFLAGS += -DCYGWIN32
EXE = .exe

View File

@@ -0,0 +1,33 @@
# CONFIG.cygwin-x86.linux-arm
#
# Definitions for cywgin-x86 host - linux-arm target builds
# Override these settings in CONFIG_SITE.cygwin-x86.linux-arm
#-------------------------------------------------------
VALID_BUILDS = Ioc
GNU_TARGET = arm-linux
# prefix of compiler tools
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))
# Library flags
STATIC_LDFLAGS_YES= -Wl,-Bstatic
STATIC_LDFLAGS_NO=
STATIC_LDLIBS_YES= -Wl,-Bdynamic
STATIC_LDLIBS_NO=

View File

@@ -0,0 +1,7 @@
# CONFIG.cygwin-x86_64.linux-arm
#
# Definitions for cygwin-x86_64 host - linux-arkm targets
# Override these settings in CONFIG_SITE.cygwin-x86_64.linux-arm
#-------------------------------------------------------
include $(CONFIG)/os/CONFIG.cygwin-x86.linux-arm

View File

@@ -0,0 +1,28 @@
# CONFIG.linux-x86.windows-x64-mingw
#
# Definitions for linux-x86 host windows-x64-mingw target builds
# Override these definitions in CONFIG_SITE.linux-x86.windows-x64-mingw
#-------------------------------------------------------
# Include common gnu compiler definitions
include $(CONFIG)/CONFIG.gnuCommon
# Add resource compiler
RCCMD = $(GNU_BIN)/$(CMPLR_PREFIX)windres$(CMPLR_SUFFIX) $(INCLUDES) $< $@
# Remove -fPIC flags, add out-implib
SHRLIB_CFLAGS =
SHRLIB_LDFLAGS = -shared \
-Wl,--out-implib,$(DLLSTUB_PREFIX)$*$(DLLSTUB_SUFFIX)
LOADABLE_SHRLIB_LDFLAGS = -shared \
-Wl,--out-implib,$(DLLSTUB_PREFIX)$*$(DLLSTUB_SUFFIX)
# No need to explicitly link with gcc library
GNU_LDLIBS_YES =
# Link with winsock2
OP_SYS_LDLIBS = -lws2_32
# Use static compiler-support libraries
OP_SYS_LDFLAGS += -static-libgcc -static-libstdc++
# There is no compiler flag for static libwinpthread

View File

@@ -0,0 +1,9 @@
# CONFIG.linux-x86_64.windows-x64-mingw
#
# Definitions for linux-x86_64 host windows-x64-mingw target builds
# Override these definitions in CONFIG_SITE.linux-x86_64.windows-x64-mingw
#-------------------------------------------------------
# Settings as for the linux-x86 host architecture
include $(CONFIG)/os/CONFIG.linux-x86.windows-x64-mingw

View File

@@ -1,22 +1,22 @@
# CONFIG_SITE.Common.cygwin-x86_64
#
# $Revision-Id$
#
# Site Specific definitions for cygwin-x86_64 target
# Only the local epics system manager should modify this file
# If readline is installed uncomment the following line
# to add command-line editing and history support
#COMMANDLINE_LIBRARY = READLINE
# Uncomment the following line if readline has problems
#LDLIBS_READLINE = -lreadline -lcurses
# It makes sense to include debugging symbols even in optimized builds
# in case you want to attach gdb to the process or examine a core-dump.
# This does cost disk space, but not memory as debug symbols are not
# loaded into RAM when the binary is loaded.
OPT_CFLAGS_YES += -g
OPT_CXXFLAGS_YES += -g
# CONFIG_SITE.Common.cygwin-x86_64
#
# $Revision-Id$
#
# Site Specific definitions for cygwin-x86_64 target
# Only the local epics system manager should modify this file
# If readline is installed uncomment the following line
# to add command-line editing and history support
#COMMANDLINE_LIBRARY = READLINE
# Uncomment the following line if readline has problems
#LDLIBS_READLINE = -lreadline -lcurses
# It makes sense to include debugging symbols even in optimized builds
# in case you want to attach gdb to the process or examine a core-dump.
# This does cost disk space, but not memory as debug symbols are not
# loaded into RAM when the binary is loaded.
OPT_CFLAGS_YES += -g
OPT_CXXFLAGS_YES += -g

View File

@@ -6,5 +6,5 @@
# Site override definitions for cygwin-x86 host builds
#-------------------------------------------------------
#CROSS_COMPILER_TARGET_ARCHS =
#CROSS_COMPILER_TARGET_ARCHS = linux-arm

View File

@@ -0,0 +1,16 @@
# CONFIG_SITE.cygwin-x86.linux-arm
#
# $Revision-Id$
#
# Site specific definitions for cygwin-x86 host - linux-arm target builds
#-------------------------------------------------------
# Tools install path
GNU_DIR = /usr/local/arm-linux
# GNU crosscompiler target name
GNU_TARGET = arm-linux
STATIC_BUILD = YES
SHARED_LIBRARIES = NO

View File

@@ -0,0 +1,16 @@
# CONFIG_SITE.cygwin-x86_64.linux-arm
#
# $Revision-Id$
#
# Site specific definitions for cygwin-x86_64 host - linux-arm target builds
#-------------------------------------------------------
# Tools install path
GNU_DIR = /usr/local/arm-linux
# GNU crosscompiler target name
GNU_TARGET = arm-linux
STATIC_BUILD = YES
SHARED_LIBRARIES = NO

View File

@@ -0,0 +1,20 @@
# CONFIG_SITE.linux-x86.windows-x64-mingw
#
# Configuration for linux-x86 host windows-x64-mingw target builds
#-------------------------------------------------------
# Early versions of the MinGW cross-build tools can only build
# static (non-DLL) libraries. For example RHEL's cross-gcc 4.4.6
# needs these uncommented, cross-gcc 4.6.3 for Ubuntu does not:
#SHARED_LIBRARIES = NO
#STATIC_BUILD = YES
# The cross-build tools are in $(GNU_DIR)/bin
# Default is /usr
#GNU_DIR = /usr/local
# Different distribution cross-build packages use different prefixes:
# Ubuntu:
#CMPLR_PREFIX = i686-w64-mingw32-
# RHEL:
CMPLR_PREFIX = x86_64-w64-mingw32-

View File

@@ -0,0 +1,8 @@
# CONFIG_SITE.linux-x86_64.windows-x64-mingw
#
# Configuration for linux-x86_64 host windows-x64-mingw target builds
#-------------------------------------------------------
# Inherit from the linux-x86 host architecture
include $(CONFIG)/os/CONFIG_SITE.linux-x86.windows-x64-mingw

View File

@@ -4,17 +4,17 @@
<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.2</title>
<title>Known Problems in R3.15.3</title>
</head>
<body>
<h1 style="text-align: center">EPICS Base R3.15.2: Known Problems</h1>
<h1 style="text-align: center">EPICS Base R3.15.3: Known Problems</h1>
<p>Any patch files linked below should be applied at the root of the
base-3.15.2 tree. Download them, then use the GNU Patch program as
base-3.15.3 tree. Download them, then use the GNU Patch program as
follows:</p>
<blockquote><pre>% <b>cd <i>/path/to/</i>base-3.15.2</b>
<blockquote><pre>% <b>cd <i>/path/to/</i>base-3.15.3</b>
% <b>patch -p0 &lt; <i>/path/to/</i>file.patch</b></pre></blockquote>
<p>The following significant problems have been reported with this
@@ -22,10 +22,18 @@ version of EPICS Base:</p>
<ul>
<li>See LaunchPad bug
<a href="https://bugs.launchpad.net/epics-base/+bug/1466129">#1466129</a>:
The feature that allows an IOC to bind to a single network interface is not
working correctly. The bug mentioned above contains a patch that has been
tested on Linux-64, a complete fix is expected for 3.15.4. Note that Windows
systems are not affected by this bug.</li>
<li>Parallel builds ("make -j") on native Windows are not working properly.
Builds tend to hang (make saturating one core) - interrupting and calling make
again usually finishes the build. Sequential builds work and are recommended
for automated build environments.</li>
Builds tend to hang (saturating one core); interrupting and running make
again usually finishes the build. Limiting the number of parallel jobs using
something like "make -j8" also helps prevent this problem. Sequential builds
always work and are recommended for automated build environments.</li>
<li>64-bit Windows builds of the CAS library may not work with some compilers.
The code in <tt>src/legacy/gdd</tt> is currently incompatible with the LLP64

View File

@@ -1,6 +1,6 @@
Installation Instructions
EPICS Base Release 3.15.2
EPICS Base Release 3.15.3
--------------------------------------------------------------------------

View File

@@ -9,7 +9,7 @@
<BODY>
<CENTER>
<H1>Installation Instructions</H1>
<H2>EPICS Base Release 3.15.2</H2><BR>
<H2>EPICS Base Release 3.15.3</H2><BR>
</CENTER>
<HR>
<H3> Table of Contents</H3>

View File

@@ -3,14 +3,270 @@
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<title>EPICS Base R3.15.2 Release Notes</title>
<title>EPICS Base R3.15.4 Release Notes</title>
</head>
<body lang="en">
<h1 align="center">EPICS Base Release 3.15.2</h1>
<h1 align="center">EPICS Base Release 3.15.4</h1>
<h2 align="center">Changes made on the 3.15 branch since 3.15.3</h2>
<!-- Insert new items immediately below here ... -->
<h3>New string input device support "getenv"</h3>
<p>A new "getenv" device support for both the stringin and lsi (long string
input) record types can be used to read the value of an environment variable
from the IOC at runtime. See base/db/softIocExit.db for sample usage.</p>
<h3>Build rules and DELAY_INSTALL_LIBS</h3>
<p>A new order-only prerequisite build rule has been added to ensure that
library files (and DLL stubs on Windows) get installed before linking any
executables, which resolves parallel build problems on high-powered CPUs. There
are some (rare) cases though where a Makefile has to build an executable and run
it to be able to compile code for a library built by the same Makefile. With
this new build rule GNUmake will complain about a circular dependency and the
build will probably fail in those cases. To avoid this problem the failing
Makefile should set <tt>DELAY_INSTALL_LIBS = YES</tt> before including the
<tt>$(TOP)/configure/RULES</tt> file, disabling the new build rule.</p>
<h3>IOC environment variables and build parameters</h3>
<p>The IOC now sets a number of environment variables at startup that provide
the version of EPICS Base it was built against (EPICS_VERSION_...) and its build
architecture (ARCH). In some cases this allows a single iocBoot/ioc directory to
be used to run the same IOC on several different architectures without any
changes.</p>
<p>There are also 3 new environment parameters (EPICS_BUILD_...) available that
C/C++ code can use to find out the target architecture, OS class and compiler
class it was built with. These may be useful when writing interfaces to other
languages.</p>
<h3>New implementation of promptgroup/gui_group field property</h3>
<p>The mechanism behind the "promptgroup()" field property inside a record type
definition has been changed. Instead of using a fixed set of choices,
the static database access library now collects the used gui group names
while parsing DBD information. Group names should start with a two-digit number
plus space-dash-space to allow proper sorting of groups.</p>
<p>The include file <tt>guigroup.h</tt> that defined the fixed set of choices
has been deprecated. Instead, use the conversion functions between index number
and group string that have been added to dbStaticLib.</p>
<p>When a DBD file containing record-type descriptions is expanded, any
old-style <tt>GUI_xxx</tt> group names will be replaced by a new-style
string for use by the IOC. This permits an older record type to be used with
the 3.15.4 release, although eventually record types should be converted by
hand with better group names used.</p>
<h3>CA server configuration changes</h3>
<p>RSRV now honors EPICS_CAS_INTF_ADDR_LIST and binds only to the provided list
of network interfaces. Name searches (UDP and TCP) on other network interfaces
are ignored. For example on a computer with interfaces 10.5.1.1/24, 10.5.2.1/24,
and 10.5.3.1/24, setting "EPICS_CAS_INTF_ADDR_LIST='10.5.1.1 10.5.2.1'" will
accept traffic on the .1.1 and .2.1, but ignore from .3.1</p>
<p>RSRV now honors EPICS_CAS_IGNORE_ADDR_LIST and ignores UDP messages received
from addresses in this list.</p>
<p>Previously, CA servers (RSRV and PCAS) would build the beacon address list
using EPICS_CA_ADDR_LIST if EPICS_CAS_BEACON_ADDR_LIST was no set. This is no
longer done. Sites depending on this should set both envronment variables to the
same value.</p>
<h3>IPv4 multicast for name search and beacons</h3>
<p>libca, RSRV, and PCAS may now use IPv4 multicasting for UDP traffic (name
search and beacons). This is disabled by default. To enable multicast address(s)
must be listed in EPICS_CA_ADDR_LIST for clients and EPICS_CAS_INTF_ADDR_LIST
for servers (IOCs should set both). For example:
"EPICS_CAS_INTF_ADDR_LIST='224.0.2.9' EPICS_CA_ADDR_LIST=224.0.2.9".</p>
<p>Please note that no IPv4 multicast address is officially assigned for Channel
Access by IANA. The example 224.0.2.9 is taken from the AD-HOC Block I range.<p>
<h3>Moved <tt>mlockall()</tt> into its own epicsThread routine</h3>
<p>Since EPICS Base 3.15.0.2 on Posix OSs the initialization of the epicsThread
subsystem has called <tt>mlockall()</tt> when the OS supports it and thread
priority scheduling is enabled. Doing so has caused problems in third-party
applications that call the CA client library, so the functionality has been
moved to a separate routine <tt>epicsThreadRealtimeLock()</tt> which will be
called by the IOC at iocInit (unless disabled by setting the global variable
<tt>dbThreadRealtimeLock</tt> to zero).</p>
<h3>Added dbQuietMacroWarnings control</h3>
<p>When loading database files, macros get expanded even on comment lines. If a
comment contains an undefined macro, the load still continues but an error
message gets printed. For this release the error message has been changed to a
warning, but even this warning can be made less verbose by setting this new
variable to a non-zero value before loading the file, like this:</p>
<blockquote><pre>
var dbQuietMacroWarnings 1 <i>iocsh</i>
dbQuietMacroWarnings=1 <i>VxWorks</i>
</pre></blockquote>
<p>This was <a href="https://bugs.launchpad.net/bugs/541119">Launchpad bug
541119</a>.</p>
<h2 align="center">Changes pulled from the 3.14 branch since 3.15.3</h2>
<!-- Insert inherited items immediately below here ... -->
<h3>Making IOC ca_get operations atomic</h3>
<p>When a CA client gets data from an IOC record using a compound data type such
as <tt>DBR_TIME_DOUBLE</tt> the value field is fetched from the database in a
separate call than the other metadata, without keeping the record locked. This
allows some other thread such as a periodic scan thread a chance to interrupt
the get operation and process the record in between. CA monitors have always
been atomic as long as the value data isn't a string or an array, but this race
condition in the CA get path has now been fixed so the record will stay locked
between the two fetch operations.</p>
<p>This fixes <a href="https://bugs.launchpad.net/epics-base/+bug/1581212">
Launchpad bug #1581212</a>, thanks to Till Strauman and Dehong Zhang.</p>
<h3>New CONFIG_SITE variable for running self-tests</h3>
<p>The 'make runtests' and 'make tapfiles' build targets normally only run the
self-tests for the main <tt>EPICS_HOST_ARCH</tt> architecture. If the host is
able to execute self-test programs for other target architectures that are being
built by the host, such as when building a <tt>-debug</tt> version of the host
architecture for example, the names of those other architectures can be added to
the new <tt>CROSS_COMPILER_RUNTEST_ARCHS</tt> variable in either the
<tt>configure/CONFIG_SITE</tt> file or in an appropriate
<tt>configure/os/CONFIG_SITE.&lt;host&gt;.Common</tt> file to have the test
programs for those targets be run as well.</p>
<h3>Additional RELEASE file checks</h3>
<p>An additional check has been added at build-time for the contents of the
configure/RELEASE file(s), which will mostly only affect users of the Debian
EPICS packages published by NSLS-2. Support modules may share an install path,
but all such modules must be listed adjacent to each other in any RELEASE files
that point to them. For example the following will fail the new checks:</p>
<blockquote><pre>
AUTOSAVE = /usr/lib/epics
ASYN = /home/mdavidsaver/asyn
EPICS_BASE = /usr/lib/epics
</pre></blockquote>
<p>giving the compile-time error</p>
<blockquote><pre>
This application's RELEASE file(s) define
EPICS_BASE = /usr/lib/epics
after but not adjacent to
AUTOSAVE = /usr/lib/epics
Module definitions that share paths must be grouped together.
Either remove a definition, or move it to a line immediately
above or below the other(s).
Any non-module definitions belong in configure/CONFIG_SITE.
</pre></blockquote>
<p>In many cases such as the one above the order of the <tt>AUTOSAVE</tt> and
<tt>ASYN</tt> lines can be swapped to let the checks pass, but if the
<tt>AUTOSAVE</tt> module depended on <tt>ASYN</tt> and hence had to appear
before it in the list this error indicates that <tt>AUTOSAVE</tt> should also be
built in its own private area; a shared copy would likely be incompatible with
the version of <tt>ASYN</tt> built in the home directory.</p>
<h3>String field buffer overflows</h3>
<p>Two buffer overflow bugs that can crash the IOC have been fixed, caused by
initializing a string field with a value larger than the field size
(<a href="https://bugs.launchpad.net/bugs/1563191">Launchpad bug
#1563191</a>).</p>
<h3>Fixed stack corruption bug in epicsThread C++ API</h3>
<p>The C++ interface to the epicsThread API could corrupt the stack on thread
exit in some rare circumstances, usually at program exit. This bug has been
fixed (<a href="https://bugs.launchpad.net/bugs/1558206">Launchpad bug
#1558206</a>).</p>
<h3>RTEMS NTP Support Issue</h3>
<p>On RTEMS the NTP Time Provider could in some circumstances get out of sync
with the server because the osdNTPGet() code wasn't clearing its input socket
before sending out a new request. This
(<a href="https://bugs.launchpad.net/bugs/1549908">Launchpad bug 1549908</a>)
has now been fixed.</p>
<h3>CALC engine bitwise operator fixes</h3>
<p>The bitwise operators in the CALC engine have been modified to work properly
with values that have bit 31 (0x80000000) set. This modification involved
back-porting some earlier changes from the 3.15 branch, and fixes
<a href="https://code.launchpad.net/bugs/1514520">Launchpad bug
#1514520</a>.</p>
<h3>Fix <tt>ipAddrToAsciiAsync()</tt>: Don't try to join the daemon thread</h3>
<p>On process exit, don't try to stop the worker thread that makes DNS lookups
asynchronous. Previously this would wait for any lookups still in progress,
delaying the exit unnecessarily. This was most obvious with catools (eg.
cainfo).
<a href="https://bugs.launchpad.net/bugs/1527636">lp:1527636</a></p>
<h3>Fix <tt>epicsTime_localtime()</tt> on Windows</h3>
<p>Simpler versions of the epicsTime_gmtime() and epicsTime_localtime()
routines have been included in the Windows implementations, and a new test
program added. The original versions do not report DST status properly. Fixes
<a href="https://bugs.launchpad.net/bugs/1528284">Launchpad bug 1528284</a>.</p>
<h2 align="center">Changes between 3.15.2 and 3.15.3</h2>
<h3>Make the NTP Time provider optional on VxWorks</h3>
<p>Recent versions of VxWorks (sometime after VxWorks 6) provide facilities for
automatically synchronizing the OS clock time with an NTP server. The EPICS time
system used to assume that it had to provide time synchronization on VxWorks,
but now it tests for the existance of either of the two OS synchronization
threads before starting the NTP time provider. It is still possible to force the
NTP provider to be started even if the OS synchronization is running by defining
the environment variable <tt>EPICS_TS_FORCE_NTPTIME</tt> in the startup script
before loading the IOC's .munch file. Forcing may be necessary if the VxWorks
image is not correctly configured with the IP address of a local NTP server.</p>
<h3>Assembling files from numbered snippets</h3>
<p>A tool has been added that assembles file snippets specified on the
command line into a single output file, with sorting and replacing/adding of
snippets done based on their file names. The build system integration requires
the output file to be specified setting COMMON_ASSEMBLIES (arch independent)
or ASSEMBLIES (created by arch), then defining the snippets for each assembly
setting *_SNIPPETS (explicitly) or *_PATTERN (searched relative to all source
directories).
</p>
<h3>Clean up after GNU readline()</h3>
<p>If EPICS Base is built with readline support, any IOC that calls epicsExit()
from a thread other than the main thread is likely to leave the user's terminal
in a weird state, requiring the user to run something like 'stty sane' to clean
it up. This release patches the readline support code to clean up automatically
by registering an epicsAtExit() routine.</p>
<h3>Removed the last vestiges of RSET::get_value()</h3>
<p>The IOC has not called the get_value() routine in the RSET for a very long
time, but there was still one implementation left in the event record support
code, and a structure definition for one of the original arguments to that
routine was defined in recGbl.h. Both of these have now been removed.</p>
<h2 align="center">Changes between 3.15.1 and 3.15.2</h2>
<!-- Insert new items immediately below here ... -->
<h3>Raised limit on link field length in database files</h3>
@@ -128,6 +384,7 @@ use a modified version of msi must provide support for both the <tt>-D</tt> and
<tt>-o&nbsp;outfile</tt> options, and should then point the MSI3_15 variable in
their applications' CONFIG_SITE files to that updated executable.</p>
<h2 align="center">Changes between 3.15.0.2 and 3.15.1</h2>
<h3>epicsStrnEscapedFromRaw() and epicsStrnRawFromEscaped()</h3>

View File

@@ -60,11 +60,8 @@ responsible for these tasks in the past and are expected to continue in the
relevent roles unless the Release Manager designates otherwise:</p>
<dl>
<dt><strong>Release Manager</strong> (Andrew Johnson)</dt>
<dd>Responsible for the release</dd>
<dt><strong>Configuration Manager</strong> (Janet Anderson)</dt>
<dd>Responsible for committing version number updates and for
creating tarfiles</dd>
<dt><strong>Release Manager</strong> (Ralph Lange)</dt>
<dd>Responsible for managing and tagging the release</dd>
<dt><strong>Platform Developers</strong></dt>
<dd>Responsible for individual operating system platforms</dd>
<dt><strong>Application Developers</strong></dt>
@@ -134,42 +131,42 @@ relevent roles unless the Release Manager designates otherwise:</p>
</tr>
<tr>
<td>&nbsp;</td>
<td>Configuration Manager</td>
<td>Release Manager</td>
<td>Edit and commit changes to the EPICS version number file
configure/CONFIG_BASE_VERSION.</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Configuration Manager</td>
<td>Release Manager</td>
<td>Tag the module in Bazaar, using these tag conventions:
<ul>
<li>
<tt>R3.15.2-pre<i>n</i></tt>
<tt>R3.15.3-pre<i>n</i></tt>
&mdash; pre-release tag
</li>
<li>
<tt>R3.15.2-rc<i>n</i></tt>
<tt>R3.15.3-rc<i>n</i></tt>
&mdash; release candidate tag, note the <tt>rc</tt> is now
lower-case</li>
</ul>
<blockquote><tt>
cd ~/base/mirror-3.15<br />
bzr tag R3.15.2-rc<i>n</i>
bzr tag R3.15.3-rc<i>n</i>
</tt></blockquote>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Configuration Manager</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:
<blockquote><tt>
cd ~/base<br />
bzr export --keywords=publish
--root=base-3.15.2-rc<i>n</i>
-r tag:R3.15.2-rc<i>n</i>
baseR3.15.2-rc<i>n</i>.tar.gz
mirror-3.15
--root=base-3.15.3-rc<i>n</i>
-r tag:R3.15.3-rc<i>n</i>
base-3.15.3-rc<i>n</i>.tar.gz
mirror-3.15
</tt></blockquote>
This requires that the Bazaar keywords plugin is installed and
configured properly.
@@ -177,14 +174,15 @@ relevent roles unless the Release Manager designates otherwise:</p>
</tr>
<tr>
<td>&nbsp;</td>
<td>Configuration Manager</td>
<td>Release Manager</td>
<td>Test the tarfile by extracting its contents and building it on at
least one supported platform.</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Configuration Manager</td>
<td>Copy the tar file to the Base download area of the website.</td>
<td>Website Manager</td>
<td>If necessary recreate the tarfile following the instructions above.
Copy the tar file to the Base download area of the website</td>
</tr>
<tr>
<td>&nbsp;</td>
@@ -223,13 +221,6 @@ relevent roles unless the Release Manager designates otherwise:</p>
<td>Run the CA client side regression tests on all available host
platforms.</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Platform Developers</td>
<td>Build and run the
<a href="https://launchpad.net/epics-base-tests">epics-base-tests</a>
suite on all available platforms.</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Platform Developers</td>
@@ -279,32 +270,32 @@ relevent roles unless the Release Manager designates otherwise:</p>
</tr>
<tr>
<td>&nbsp;</td>
<td>Configuration Manager</td>
<td>Release Manager</td>
<td>Edit and commit changes to the EPICS version number file
configure/CONFIG_BASE_VERSION.</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Configuration Manager</td>
<td>Release Manager</td>
<td>Tag the module in Bazaar:
<blockquote><tt>
cd ~/base/mirror-3.15<br />
bzr tag R3.15.2</i>
bzr tag R3.15.3</i>
</tt></blockquote>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>Configuration Manager</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:
<blockquote><tt>
cd ~/base<br />
bzr export --keywords=publish
--root=base-3.15.2
-r tag:R3.15.2
baseR3.15.2.tar.gz
mirror-3.15
--root=base-3.15.3
-r tag:R3.15.3
base-3.15.3.tar.gz
mirror-3.15
</tt></blockquote>
This requires that the Bazaar keywords plugin is installed and
configured properly.
@@ -312,7 +303,7 @@ relevent roles unless the Release Manager designates otherwise:</p>
</tr>
<tr>
<td>&nbsp;</td>
<td>Configuration Manager</td>
<td>Release Manager</td>
<td>Test the tar file by extracting its contents and building it on at
least one supported platform</td>
</tr>
@@ -321,8 +312,9 @@ relevent roles unless the Release Manager designates otherwise:</p>
</tr>
<tr>
<td>&nbsp;</td>
<td>Configuration Manager</td>
<td>Copy the tar file to the Base download area of the website</td>
<td>Website Manager</td>
<td>If necessary recreate the tarfile following the instructions above.
Copy the tar file to the Base download area of the website</td>
</tr>
<tr>
<td>&nbsp;</td>

View File

@@ -209,6 +209,7 @@ $Date$</span></small></p>
<li><a href="#ca_pend_event">ca_poll</a></li>
<li><a href="#ca_puser">ca_puser</a></li>
<li><a href="#ca_put">ca_put</a></li>
<li><a href="#ca_put">ca_put_callback</a></li>
<li><a href="#ca_set_puser">ca_set_puser</a></li>
<li><a href="#ca_signal">ca_signal</a></li>
<li><a href="#ca_sg_block">ca_sg_block</a></li>
@@ -223,7 +224,7 @@ $Date$</span></small></p>
<li><a href="#ca_test_io">ca_test_io</a></li>
<li><a href="#ca_write_access">ca_write_access</a></li>
<li><a href="#ca_state">channel_state</a></li>
<li><a href="#dbr_size[]">dbr_size[]</a></li>
<li><a href="#dbr_size">dbr_size[]</a></li>
<li><a href="#dbr_size_n">dbr_size_n</a></li>
<li><a href="#dbr_value_size">dbr_value_size[]</a></li>
<li><a href="#dbr_type_t">dbr_type_to_text</a></li>
@@ -840,23 +841,18 @@ seconds. See also <a href="#Disconnect">EPICS_CA_CONN_TMO</a> and
Interval</a>.</p>
<p>CA servers build a list of addresses to send beacons to during
initialization. If EPICS_CAS_AUTO_BEACON_ADDR_LIST has the value "YES" then the
beacon address list will be automatically configured to contain the broadcast
addresses of all LAN interfaces found in the host and the destination address
of all point-to-point interfaces found in the host. However, if the user also
initialization. If EPICS_CAS_AUTO_BEACON_ADDR_LIST has the value "YES"
(the default) this list will be automatically populated with the broadcast
addresses of all network interfaces. However, if the user also
defines EPICS_CAS_INTF_ADDR_LIST then beacon address list automatic
configuration is constrained to the network interfaces specified therein, and
therefore only the broadcast addresses of the specified LAN interfaces, and the
destination addresses of all specified point-to-point links, will be
therefore only the broadcast addresses of the specified LAN interfaces, will be
automatically configured.</p>
<p>If EPICS_CAS_BEACON_ADDR_LIST is defined then its contents will be used to
augment any automatic configuration of the beacon address list. Individual
entries in EPICS_CAS_BEACON_ADDR_LIST may override the destination port number
if ":nnn" follows the host name or IP address there. Alternatively, when both
EPICS_CAS_BEACON_ADDR_LIST and EPICS_CAS_INTF_ADDR_LIST are not defined then
the contents of EPICS_CA_ADDR_LIST is used to augment the list. Otherwise, the
list is not augmented.</p>
if ":nnn" follows the host name or IP address there.</p>
<p>The EPICS_CAS_BEACON_PORT parameter specifies the destination port for
server beacons. The only exception to this occurs when ports are specified in
@@ -867,20 +863,18 @@ specified in EPICS_CA_REPEATER_PORT.</p>
<h4>Binding a Server to a Limited Set of Network Interfaces</h4>
<p>The parameter EPICS_CAS_INTF_ADDR_LIST allows a ca server to bind itself to,
and therefore accept messages only over, a limited set of the local host's
and therefore accept messages received by, a limited set of the local host's
network interfaces (each specified by its IP address). On UNIX systems type
"netstat -i" (type "ipconfig" on windows) to see a list of the local host's
network interfaces. Specifically, UDP search messages addressed to both the IP
addresses in EPICS_CAS_INTF_ADDR_LIST and also to the broadcast addresses of
the corresponding LAN interfaces will be accepted by the server. By default,
"netstat -ie" (type "ipconfig" on windows) to see a list of the local host's
network interfaces. By default,
the CA server is accessible from all network interfaces configured into its
host.</p>
<p>In R3.14 and previous releases the CA server employed by iocCore did not
implement the EPICS_CAS_INTF_ADDR_LIST feature. In this release the iocCore
server will read the first IP address from the parameter variable and use that
to select which interface to bind to. Any additional IP addresses will be
ignored and a warning message displayed during IOC initialization.</p>
<p>Until R3.15.4 the CA server employed by iocCore did not
implement the EPICS_CAS_INTF_ADDR_LIST feature.</p>
<p>Prior to R3.15.4 CA servers would build the beacon address list
using EPICS_CA_ADDR_LIST if EPICS_CAS_BEACON_ADDR_LIST was no set.</p>
<h4>Ignoring Process Variable Name Resolution Requests From Certain Hosts</h4>
@@ -3831,7 +3825,7 @@ specified channel and boolean false otherwise.</p>
channel and boolean false otherwise</dd>
</dl>
<h3><code><a name="dbr_size[]">dbr_size[]</a></code></h3>
<h3><code><a name="dbr_size">dbr_size[]</a></code></h3>
<pre>#include &lt;db_access.h&gt;
extern unsigned dbr_size[/* TYPE */];</pre>
@@ -3953,11 +3947,12 @@ int ca_sg_create ( CA_SYNC_GID *PGID );</pre>
<p>A synchronous group can be used to guarantee that a set of channel access
requests have completed. Once a synchronous group has been created then channel
access get and put requests may be issued within it using <code>ca_sg_get()</code> and
<code>ca_sg_put()</code> respectively. The routines <code>ca_sg_block()</code> and <code>ca_sg_test()</code> can be
access get and put requests may be issued within it using
<code>ca_sg_array_get()</code> and <code>ca_sg_array_put()</code> respectively.
The routines <code>ca_sg_block()</code> and <code>ca_sg_test()</code> can be
used to block for and test for completion respectively. The routine
<code>ca_sg_reset()</code> is used to discard knowledge of old requests which have timed out
and in all likelihood will never be satisfied.</p>
<code>ca_sg_reset()</code> is used to discard knowledge of old requests which
have timed out and in all likelihood will never be satisfied.</p>
<p>Any number of asynchronous groups can have application requested operations
outstanding within them at any given time.</p>
@@ -4131,16 +4126,20 @@ status = ca_sg_reset(gid);</pre>
<h3><code><a name="ca_sg_put">ca_sg_array_put()</a></code></h3>
<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,
unsigned long COUNT, chid CHID, void *PVALUE );</pre>
<p>Write a value, or array of values, to a channel and increment the
outstanding request count of a synchronous group. The <code>ca_sg_array_put()</code>
functionality is implemented using <code>ca_array_put_callback()</code>.</p>
<p>Write a value, or array of values, to a channel and increment the outstanding
request count of a synchronous group. The <code>ca_sg_put()</code> and
<code>ca_sg_array_put()</code> functionality is implemented using
<code>ca_array_put_callback()</code>.</p>
<p>All remote operation requests such as the above are accumulated (buffered)
and not forwarded to the server 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. This allows several requests to be
and not forwarded to the server 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. This allows several requests to be
efficiently sent in one message.</p>
<p>If a connection is lost and then resumed outstanding puts are not
@@ -4193,6 +4192,8 @@ reissued.</p>
<h3><code><a name="ca_sg_get">ca_sg_array_get()</a></code></h3>
<pre>#include &lt;cadef.h&gt;
int ca_sg_get ( CA_SYNC_GID GID, chtype TYPE,
chid CHID, void *PVALUE );
int ca_sg_array_get ( CA_SYNC_GID GID,
chtype TYPE, unsigned long COUNT,
chid CHID, void *PVALUE );</pre>
@@ -4200,16 +4201,19 @@ int ca_sg_array_get ( CA_SYNC_GID GID,
<h4>Description</h4>
<p>Read a value from a channel and increment the outstanding request count of a
synchronous group. The <code>ca_sg_array_get()</code> functionality is implemented using
synchronous group. The <code>ca_sg_get()</code> and
<code>ca_sg_array_get()</code> functionality is implemented using
<code>ca_array_get_callback()</code>.</p>
<p>The values written into your program's variables by <code>ca_sg_get()</code> should not be
referenced by your program until ECA_NORMAL has been received from <code>ca_sg_block()</code>,
or until <code>ca_sg_test()</code> returns ECA_IODONE.</p>
<p>The values written into your program's variables by <code>ca_sg_get()</code>
or <code>ca_sg_array_get()</code> should not be referenced by your program until
ECA_NORMAL has been received from <code>ca_sg_block()</code>, or until
<code>ca_sg_test()</code> returns ECA_IODONE.</p>
<p>All remote operation requests such as the above are accumulated (buffered)
and not forwarded to the server 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. This allows several requests to be
and not forwarded to the server 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. This allows several requests to be
efficiently sent in one message.</p>
<p>If a connection is lost and then resumed outstanding gets are not

View File

@@ -22,7 +22,7 @@ extern "C" {
epicsShareFunc void epicsShareAPI configureChannelAccessAddressList
( struct ELLLIST *pList, SOCKET sock, unsigned short port );
epicsShareFunc void epicsShareAPI addAddrToChannelAccessAddressList
epicsShareFunc int epicsShareAPI addAddrToChannelAccessAddressList
( struct ELLLIST *pList, const ENV_PARAM *pEnv,
unsigned short port, int ignoreNonDefaultPort );

View File

@@ -333,6 +333,12 @@ cac::~cac ()
this->ipToAEngine.release ();
// clean-up the list of un-notified msg objects
while ( msgForMultiplyDefinedPV * msg = this->msgMultiPVList.get() ) {
msg->~msgForMultiplyDefinedPV ();
this->mdpvFreeList.release ( msg );
}
errlogFlush ();
osiSockRelease ();
@@ -606,6 +612,8 @@ void cac::transferChanToVirtCircuit (
msgForMultiplyDefinedPV * pMsg = new ( this->mdpvFreeList )
msgForMultiplyDefinedPV ( this->ipToAEngine,
*this, pChan->pName ( guard ), acc );
// cac keeps a list of these objects for proper clean-up in ~cac
this->msgMultiPVList.add ( *pMsg );
// It is possible for the ioInitiate call below to
// call the callback directly if queue quota is exceeded.
// This callback takes the callback lock and therefore we
@@ -1297,6 +1305,8 @@ void cac::pvMultiplyDefinedNotify ( msgForMultiplyDefinedPV & mfmdpv,
epicsGuard < epicsMutex > guard ( this->mutex );
this->exception ( mgr.cbGuard, guard, ECA_DBLCHNL, buf, __FILE__, __LINE__ );
}
// remove from the list and delete msg object
this->msgMultiPVList.remove ( mfmdpv );
mfmdpv.~msgForMultiplyDefinedPV ();
this->mdpvFreeList.release ( & mfmdpv );
}

View File

@@ -237,6 +237,7 @@ private:
resTable < tcpiiu, caServerID > serverTable;
tsDLList < tcpiiu > circuitList;
tsDLList < SearchDest > searchDestList;
tsDLList < msgForMultiplyDefinedPV > msgMultiPVList;
tsFreeList
< class tcpiiu, 32, epicsMutexNOOP >
freeListVirtualCircuit;

View File

@@ -73,7 +73,7 @@ static char *getToken ( const char **ppString, char *pBuf, unsigned bufSIze )
/*
* addAddrToChannelAccessAddressList ()
*/
extern "C" void epicsShareAPI addAddrToChannelAccessAddressList
extern "C" int epicsShareAPI addAddrToChannelAccessAddressList
( ELLLIST *pList, const ENV_PARAM *pEnv,
unsigned short port, int ignoreNonDefaultPort )
{
@@ -82,11 +82,11 @@ extern "C" void epicsShareAPI addAddrToChannelAccessAddressList
const char *pToken;
struct sockaddr_in addr;
char buf[32u]; /* large enough to hold an IP address */
int status;
int status, ret = -1;
pStr = envGetConfigParamPtr (pEnv);
if (!pStr) {
return;
return ret;
}
while ( ( pToken = getToken (&pStr, buf, sizeof (buf) ) ) ) {
@@ -104,7 +104,7 @@ extern "C" void epicsShareAPI addAddrToChannelAccessAddressList
pNewNode = (osiSockAddrNode *) calloc (1, sizeof(*pNewNode));
if (pNewNode==NULL) {
fprintf ( stderr, "addAddrToChannelAccessAddressList(): no memory available for configuration\n");
return;
break;
}
pNewNode->addr.ia = addr;
@@ -113,9 +113,10 @@ extern "C" void epicsShareAPI addAddrToChannelAccessAddressList
* LOCK applied externally
*/
ellAdd (pList, &pNewNode->node);
ret = 0; /* success if anything is added to the list */
}
return;
return ret;
}
/*

View File

@@ -55,8 +55,10 @@ msgForMultiplyDefinedPV::~msgForMultiplyDefinedPV ()
void msgForMultiplyDefinedPV::transactionComplete ( const char * pHostNameRej )
{
// calls into cac for the notification
// the msg object (= this) is being deleted as part of the notification
this->cb.pvMultiplyDefinedNotify ( *this, this->channel, this->acc, pHostNameRej );
// !! dont touch this pointer after this point because object has been deleted !!
// !! dont touch 'this' pointer after this point because object has been deleted !!
}
void * msgForMultiplyDefinedPV::operator new ( size_t size,

View File

@@ -33,6 +33,7 @@
#include "ipAddrToAsciiAsynchronous.h"
#include "tsFreeList.h"
#include "tsDLList.h"
#include "compilerDependencies.h"
#ifdef msgForMultiplyDefinedPVh_epicsExportSharedSymbols
@@ -47,7 +48,9 @@ public:
const char * pAcc, const char * pRej ) = 0;
};
class msgForMultiplyDefinedPV : public ipAddrToAsciiCallBack {
class msgForMultiplyDefinedPV :
public ipAddrToAsciiCallBack,
public tsDLNode < msgForMultiplyDefinedPV > {
public:
msgForMultiplyDefinedPV ( ipAddrToAsciiEngine & engine,
callbackForMultiplyDefinedPV &, const char * pChannelName,
@@ -62,8 +65,8 @@ private:
ipAddrToAsciiTransaction & dnsTransaction;
callbackForMultiplyDefinedPV & cb;
void transactionComplete ( const char * pHostName );
msgForMultiplyDefinedPV ( const msgForMultiplyDefinedPV & );
msgForMultiplyDefinedPV & operator = ( const msgForMultiplyDefinedPV & );
msgForMultiplyDefinedPV ( const msgForMultiplyDefinedPV & );
msgForMultiplyDefinedPV & operator = ( const msgForMultiplyDefinedPV & );
void operator delete ( void * );
};

View File

@@ -1138,6 +1138,20 @@ void CA_add_exception_event(const char *class, SV *sub) {
static
SV * printf_sub = NULL;
#ifndef va_copy
# ifdef __GNUC__
# define va_copy(d, s) __va_copy(d, s)
# else
# define va_copy(d, s) ((d) = (s))
/* The above macro is NOT PORTABLE but works on Windows when
* stdarg.h doesn't provide va_copy(). Some architectures need
* define va_copy(d, s) ((*d) = (*s))
* while others may be even more complicated, but hopefully the
* system stdarg.h header defines va_copy() in those cases.
*/
# endif
#endif
static
int printf_handler(const char *format, va_list args) {
if (! printf_sub)
@@ -1152,11 +1166,7 @@ int printf_handler(const char *format, va_list args) {
ENTER;
SAVETMPS;
#ifdef __GNUC__
__va_copy(argcopy, args);
#else
va_copy(argcopy, args);
#endif
printf_str = NEWSV(0, strlen(format) + 32);
sv_vsetpvf(printf_str, format, &argcopy);

View File

@@ -20,10 +20,19 @@ ifeq ($(OS_CLASS),Darwin)
LOADABLE_SHRLIB_SUFFIX = .$(shell $(PERL) ../perlConfig.pl dlext)
endif
PERL_VERSION = $(shell $(PERL) ../perlConfig.pl version)
PERL_ARCHNAME = $(shell $(PERL) ../perlConfig.pl archname)
PERL_ARCHPATH = $(PERL_VERSION)/$(PERL_ARCHNAME)
ifdef T_A
PERL_VERSION = $(shell $(PERL) ../perlConfig.pl version)
PERL_ARCHNAME = $(shell $(PERL) ../perlConfig.pl archname)
PERL_ARCHPATH := $(PERL_VERSION)/$(PERL_ARCHNAME)
EXTUTILS := $(shell $(PERL) ../perlConfig.pl privlib)/ExtUtils
PERLBIN := $(shell $(PERL) ../perlConfig.pl bin)
XSUBPP := $(firstword $(wildcard $(PERLBIN)/xsubpp $(EXTUTILS)/xsubpp))
ifeq ($(strip $(XSUBPP)),)
$(warning Perl's xsubpp program was not found.)
$(warning The Perl CA module will not be built.)
else
ifeq ($(T_A),$(EPICS_HOST_ARCH)) # No cross-builds (wrong Perl!)
ifeq ($(findstring $(OS_CLASS),WIN32 cygwin32),) # Doesn't build on WIN32
LOADABLE_LIBRARY_HOST = Cap5
@@ -41,6 +50,8 @@ ifeq ($(findstring $(OS_CLASS),WIN32 cygwin32),) # Doesn't build on WIN32
HTMLS = CA.html
endif
endif
endif
endif
Cap5_SRCS = Cap5.xs
Cap5_LIBS = ca Com
@@ -52,10 +63,6 @@ CLEANS += Cap5.c pod2htmd.tmp pod2htmi.tmp
include $(TOP)/configure/RULES
ifdef T_A
EXTUTILS = $(shell $(PERL) ../perlConfig.pl privlib)/ExtUtils
PERLBIN = $(shell $(PERL) ../perlConfig.pl bin)
XSUBPP = $(firstword $(wildcard $(PERLBIN)/xsubpp $(EXTUTILS)/xsubpp))
%.c: ../%.xs
$(RM) $@ $@_new
$(PERL) $(XSUBPP) -typemap $(EXTUTILS)/typemap $< > $@_new && $(MV) $@_new $@

View File

@@ -3,7 +3,13 @@
# This script is used to extract information about the Perl build
# configuration, so the EPICS build system uses the same settings.
use strict;
use Config;
my $arg = shift;
print $Config{$arg};
my $val = $Config{$arg};
$val =~ s{\\}{/}go
if $^O eq 'MSWin32';
print $val;

View File

@@ -492,14 +492,13 @@ int main (int argc, char *argv[])
} else { /* Not an ENUM */
if (charArrAsStr) {
count = len;
dbrType = DBR_CHAR;
ebuf = calloc(strlen(cbuf)+1, sizeof(char));
ebuf = calloc(len, sizeof(char));
if(!ebuf) {
fprintf(stderr, "Memory allocation failed\n");
return 1;
}
epicsStrnRawFromEscaped(ebuf, strlen(cbuf)+1, cbuf, strlen(cbuf));
count = epicsStrnRawFromEscaped(ebuf, len, cbuf, len-1) + 1;
} else {
for (i = 0; i < count; ++i) {
epicsStrnRawFromEscaped(sbuf[i], sizeof(EpicsStr), *(argv+optind+i), sizeof(EpicsStr));

View File

@@ -163,6 +163,19 @@ udpiiu::udpiiu (
throwWithLocation ( noSocket () );
}
#ifdef IP_ADD_MEMBERSHIP
{
int flag = 1;
if ( setsockopt ( this->sock, IPPROTO_IP, IP_MULTICAST_LOOP,
(char *) &flag, sizeof ( flag ) ) == -1 ) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
errlogPrintf("CAC: failed to set mcast loopback\n");
}
}
#endif
int boolValue = true;
int status = setsockopt ( this->sock, SOL_SOCKET, SO_BROADCAST,
(char *) &boolValue, sizeof ( boolValue ) );

View File

@@ -69,6 +69,11 @@ CLEANS += $(COMMON_DIR)/aitConvertGenerated.cc
USR_CXXFLAGS_Linux = -fno-strict-aliasing
USR_CXXFLAGS_RTEMS = -fno-strict-aliasing
ifeq ($(T_A),$(EPICS_HOST_ARCH))
# genApps and aitGen are needed to finish libgdd
DELAY_INSTALL_LIBS = YES
endif
include $(TOP)/configure/RULES
# Manual dependencies

View File

@@ -141,6 +141,39 @@ caStatus caServerI::attachInterface ( const caNetAddr & addrIn,
return S_cas_success;
}
void caServerI::addMCast(const osiSockAddr& addr)
{
#ifdef IP_ADD_MEMBERSHIP
epicsGuard < epicsMutex > locker ( this->mutex );
tsDLIter < casIntfOS > iter = this->intfList.firstIter ();
while ( iter.valid () ) {
struct ip_mreq mreq;
memset(&mreq, 0, sizeof(mreq));
mreq.imr_interface = iter->serverAddress().getSockIP().sin_addr;
mreq.imr_multiaddr = addr.ia.sin_addr;
if ( setsockopt ( iter->casDGIntfIO::getFD (), IPPROTO_IP,
IP_ADD_MEMBERSHIP, (char *) &mreq,
sizeof ( mreq ) ) < 0) {
struct sockaddr_in temp;
char name[40];
char sockErrBuf[64];
temp.sin_family = AF_INET;
temp.sin_addr = mreq.imr_multiaddr;
temp.sin_port = addr.ia.sin_port;
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
ipAddrToDottedIP (&temp, name, sizeof(name));
fprintf(stderr, "CAS: Socket mcast join %s failed with \"%s\"\n",
name, sockErrBuf );
}
iter++;
}
#endif
}
void caServerI::sendBeacon ( ca_uint32_t beaconNo )
{
epicsGuard < epicsMutex > locker ( this->mutex );

View File

@@ -103,6 +103,8 @@ private:
caStatus attachInterface ( const caNetAddr & addr, bool autoBeaconAddr,
bool addConfigAddr );
virtual void addMCast(const osiSockAddr&);
void sendBeacon ( ca_uint32_t beaconNo );
caServerI ( const caServerI & );

View File

@@ -348,10 +348,8 @@ caStatus casDGClient::searchResponse ( const caHdrLargeArray & msg,
//
caStatus casDGClient::searchFailResponse ( const caHdrLargeArray * mp )
{
int status;
epicsGuard < epicsMutex > guard ( this->mutex );
status = this->out.copyInHeader ( CA_PROTO_NOT_FOUND, 0,
this->out.copyInHeader ( CA_PROTO_NOT_FOUND, 0,
mp->m_dataType, mp->m_count, mp->m_cid, mp->m_available, 0 );
this->out.commitMsg ();

View File

@@ -14,6 +14,7 @@
//
#include <ctype.h>
#include <list>
#include "epicsSignal.h"
#include "envDefs.h"
@@ -92,6 +93,9 @@ void caServerIO::locateInterfaces ()
autoBeaconAddr = true;
}
typedef std::list<osiSockAddr> mcastAddrs_t;
mcastAddrs_t mcastAddrs;
//
// bind to the the interfaces specified - otherwise wildcard
// with INADDR_ANY and allow clients to attach from any interface
@@ -114,6 +118,15 @@ void caServerIO::locateInterfaces ()
pToken);
continue;
}
epicsUInt32 top = ntohl(saddr.sin_addr.s_addr)>>24;
if (saddr.sin_family==AF_INET && top>=224 && top<=239) {
osiSockAddr oaddr;
oaddr.ia = saddr;
mcastAddrs.push_back(oaddr);
continue;
}
stat = this->attachInterface (caNetAddr(saddr), autoBeaconAddr, configAddrOnceFlag);
if (stat) {
errMessage(stat, "unable to attach explicit interface");
@@ -131,6 +144,10 @@ void caServerIO::locateInterfaces ()
errMessage(stat, "unable to attach any interface");
}
}
for (mcastAddrs_t::const_iterator it = mcastAddrs.begin(); it!=mcastAddrs.end(); ++it) {
this->addMCast(*it);
}
}
//

View File

@@ -47,6 +47,8 @@ private:
virtual caStatus attachInterface (
const caNetAddr & addr, bool autoBeaconAddr,
bool addConfigAddr ) = 0;
virtual void addMCast(const osiSockAddr&) = 0;
};
#endif // caServerIOh

View File

@@ -19,6 +19,11 @@
#include "addrList.h"
#include "errlog.h"
#if defined(_MSC_VER)
# include <BaseTsd.h>
typedef SSIZE_T ssize_t;
#endif
#define epicsExportSharedSymbols
#include "casDGIntfIO.h"
#include "ipIgnoreEntry.h"
@@ -148,26 +153,8 @@ casDGIntfIO::casDGIntfIO ( caServerI & serverIn, clientBufMemoryManager & memMgr
}
if ( addConfigBeaconAddr ) {
//
// by default use EPICS_CA_ADDR_LIST for the
// beacon address list
//
const ENV_PARAM *pParam;
if ( envGetConfigParamPtr ( & EPICS_CAS_INTF_ADDR_LIST ) ||
envGetConfigParamPtr ( & EPICS_CAS_BEACON_ADDR_LIST ) ) {
pParam = & EPICS_CAS_BEACON_ADDR_LIST;
}
else {
pParam = & EPICS_CA_ADDR_LIST;
}
//
// add in the configured addresses
//
addAddrToChannelAccessAddressList (
& BCastAddrList, pParam, beaconPort, pParam == & EPICS_CA_ADDR_LIST );
& BCastAddrList, &EPICS_CAS_BEACON_ADDR_LIST, beaconPort, 0 );
}
removeDuplicateAddresses ( & this->beaconAddrList, & BCastAddrList, 0 );
@@ -267,7 +254,7 @@ casDGIntfIO::~casDGIntfIO()
// avoid use of ellFree because problems on windows occur if the
// free is in a different DLL than the malloc
ELLNODE * nnode = this->beaconAddrList.node.next;
ELLNODE * nnode = ellFirst(&this->beaconAddrList);
while ( nnode )
{
ELLNODE * pnode = nnode;
@@ -418,52 +405,24 @@ bufSizeT casDGIntfIO ::
}
void casDGIntfIO::sendBeaconIO ( char & msg, unsigned length,
aitUint16 & portField, aitUint32 & addrField )
aitUint16 & portField, aitUint32 & )
{
caNetAddr addr = this->serverAddress ();
struct sockaddr_in inetAddr = addr.getSockIP();
osiSockAddrNode *pAddr;
int status;
char buf[64];
portField = inetAddr.sin_port; // the TCP port
for (pAddr = reinterpret_cast <osiSockAddrNode *> ( ellFirst ( & this->beaconAddrList ) );
pAddr; pAddr = reinterpret_cast <osiSockAddrNode *> ( ellNext ( & pAddr->node ) ) ) {
status = connect ( this->beaconSock, &pAddr->addr.sa, sizeof ( pAddr->addr.sa ) );
if (status<0) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
ipAddrToDottedIP ( & pAddr->addr.ia, buf, sizeof ( buf ) );
errlogPrintf ( "%s: CA beacon routing (connect to \"%s\") error was \"%s\"\n",
__FILE__, buf, sockErrBuf );
}
else {
osiSockAddr sockAddr;
osiSocklen_t size = ( osiSocklen_t ) sizeof ( sockAddr.sa );
status = getsockname ( this->beaconSock, &sockAddr.sa, &size );
if ( status < 0 ) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
errlogPrintf ( "%s: CA beacon routing (getsockname) error was \"%s\"\n",
__FILE__, sockErrBuf );
}
else if ( sockAddr.sa.sa_family == AF_INET ) {
addrField = sockAddr.ia.sin_addr.s_addr;
for (ELLNODE *pNode = ellFirst(&this->beaconAddrList); pNode; pNode = ellNext(pNode))
{
osiSockAddrNode *pAddr = reinterpret_cast<osiSockAddrNode *>(pNode);
status = send ( this->beaconSock, &msg, length, 0 );
if ( status < 0 ) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
ipAddrToA ( &pAddr->addr.ia, buf, sizeof(buf) );
errlogPrintf ( "%s: CA beacon (send to \"%s\") error was \"%s\"\n",
__FILE__, buf, sockErrBuf );
}
else {
unsigned statusAsLength = static_cast < unsigned > ( status );
assert ( statusAsLength == length );
}
}
ssize_t status = sendto(this->beaconSock, &msg, length, 0, &pAddr->addr.sa, sizeof(pAddr->addr.ia));
if ( status != length ) {
char sockErrBuf[64], buf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
ipAddrToA ( &pAddr->addr.ia, buf, sizeof(buf) );
errlogPrintf ( "%s: CA beacon (send to \"%s\") error was \"%s\" (%u)\n",
__FILE__, buf, sockErrBuf, (unsigned)status );
}
}
}

View File

@@ -54,6 +54,7 @@ typedef struct cbQueueSet {
epicsEventId semWakeUp;
epicsRingPointerId queue;
int queueOverflow;
int shutdown;
int threadsConfigured;
int threadsRunning;
} cbQueueSet;
@@ -73,7 +74,8 @@ static epicsTimerQueueId timerQueue;
enum ctl {ctlInit, ctlRun, ctlPause, ctlExit};
static volatile enum ctl cbCtl;
static epicsEventId startStopEvent;
static void *exitCallback;
static int callbackIsInit;
/* Static data */
static char *threadNamePrefix[NUM_CALLBACK_PRIORITIES] = {
@@ -89,7 +91,7 @@ static int priorityValue[NUM_CALLBACK_PRIORITIES] = {0, 1, 2};
int callbackSetQueueSize(int size)
{
if (startStopEvent) {
if (callbackIsInit) {
errlogPrintf("Callback system already initialized\n");
return -1;
}
@@ -99,7 +101,7 @@ int callbackSetQueueSize(int size)
int callbackParallelThreads(int count, const char *prio)
{
if (startStopEvent) {
if (callbackIsInit) {
errlogPrintf("Callback system already initialized\n");
return -1;
}
@@ -149,12 +151,13 @@ int callbackParallelThreads(int count, const char *prio)
static void callbackTask(void *arg)
{
cbQueueSet *mySet = &callbackQueue[*(int*)arg];
int prio = *(int*)arg;
cbQueueSet *mySet = &callbackQueue[prio];
taskwdInsert(0, NULL, NULL);
epicsEventSignal(startStopEvent);
while(TRUE) {
while(!mySet->shutdown) {
void *ptr;
if (epicsRingPointerIsEmpty(mySet->queue))
epicsEventMustWait(mySet->semWakeUp);
@@ -163,42 +166,52 @@ static void callbackTask(void *arg)
CALLBACK *pcallback = (CALLBACK *)ptr;
if(!epicsRingPointerIsEmpty(mySet->queue))
epicsEventMustTrigger(mySet->semWakeUp);
if (ptr == &exitCallback) goto shutdown;
mySet->queueOverflow = FALSE;
(*pcallback->callback)(pcallback);
}
}
shutdown:
mySet->threadsRunning--;
if(!epicsAtomicDecrIntT(&mySet->threadsRunning))
epicsEventSignal(startStopEvent);
taskwdRemove(0);
epicsEventSignal(startStopEvent);
}
void callbackShutdown(void)
void callbackStop(void)
{
int i;
if (cbCtl == ctlExit) return;
cbCtl = ctlExit;
/* sequential shutdown of workers */
for (i = 0; i < NUM_CALLBACK_PRIORITIES; i++) {
while (callbackQueue[i].threadsRunning) {
if(epicsRingPointerPush(callbackQueue[i].queue, &exitCallback)) {
epicsEventSignal(callbackQueue[i].semWakeUp);
epicsEventWait(startStopEvent);
} else {
epicsThreadSleep(0.05);
}
}
assert(callbackQueue[i].threadsRunning==0);
epicsEventDestroy(callbackQueue[i].semWakeUp);
epicsRingPointerDelete(callbackQueue[i].queue);
callbackQueue[i].shutdown = 1;
epicsEventSignal(callbackQueue[i].semWakeUp);
}
for (i = 0; i < NUM_CALLBACK_PRIORITIES; i++) {
cbQueueSet *mySet = &callbackQueue[i];
while (epicsAtomicGetIntT(&mySet->threadsRunning)) {
epicsEventSignal(mySet->semWakeUp);
epicsEventWaitWithTimeout(startStopEvent, 0.1);
}
}
}
void callbackCleanup(void)
{
int i;
for (i = 0; i < NUM_CALLBACK_PRIORITIES; i++) {
cbQueueSet *mySet = &callbackQueue[i];
assert(epicsAtomicGetIntT(&mySet->threadsRunning)==0);
epicsEventDestroy(mySet->semWakeUp);
epicsRingPointerDelete(mySet->queue);
}
epicsTimerQueueRelease(timerQueue);
epicsEventDestroy(startStopEvent);
startStopEvent = NULL;
callbackIsInit = 0;
memset(callbackQueue, 0, sizeof(callbackQueue));
}
@@ -208,10 +221,14 @@ void callbackInit(void)
int j;
char threadName[32];
if (startStopEvent)
if (callbackIsInit) {
errlogMessage("Warning: callbackInit called again before callbackCleanup\n");
return;
}
callbackIsInit = 1;
startStopEvent = epicsEventMustCreate(epicsEventEmpty);
if(!startStopEvent)
startStopEvent = epicsEventMustCreate(epicsEventEmpty);
cbCtl = ctlRun;
timerQueue = epicsTimerQueueAllocate(0, epicsThreadPriorityScanHigh);
@@ -239,7 +256,7 @@ void callbackInit(void)
cantProceed("Failed to spawn callback thread %s\n", threadName);
} else {
epicsEventWait(startStopEvent);
callbackQueue[i].threadsRunning++;
epicsAtomicIncrIntT(&callbackQueue[i].threadsRunning);
}
}
}

View File

@@ -57,7 +57,8 @@ typedef void (*CALLBACKFUNC)(struct callbackPvt*);
( (USER) = (void *)((CALLBACK *)(PCALLBACK))->user )
epicsShareFunc void callbackInit(void);
epicsShareFunc void callbackShutdown(void);
epicsShareFunc void callbackStop(void);
epicsShareFunc void callbackCleanup(void);
epicsShareFunc int callbackRequest(CALLBACK *pCallback);
epicsShareFunc void callbackSetProcess(
CALLBACK *pcallback, int Priority, void *pRec);

View File

@@ -402,19 +402,29 @@ struct rset * dbGetRset(const struct dbAddr *paddr)
}
long dbPutAttribute(
const char *recordTypename,const char *name,const char*value)
const char *recordTypename, const char *name, const char *value)
{
DBENTRY dbEntry;
DBENTRY *pdbEntry = &dbEntry;
long status=0;
DBENTRY dbEntry;
DBENTRY *pdbEntry = &dbEntry;
long status = 0;
if(!pdbbase) return(S_db_notFound);
dbInitEntry(pdbbase,pdbEntry);
status = dbFindRecordType(pdbEntry,recordTypename);
if(!status) status = dbPutRecordAttribute(pdbEntry,name,value);
dbFinishEntry(pdbEntry);
if(status) errMessage(status,"dbPutAttribute failure");
return(status);
if (!pdbbase)
return S_db_notFound;
if (!name) {
status = S_db_badField;
goto done;
}
if (!value)
value = "";
dbInitEntry(pdbbase, pdbEntry);
status = dbFindRecordType(pdbEntry, recordTypename);
if (!status)
status = dbPutRecordAttribute(pdbEntry, name, value);
dbFinishEntry(pdbEntry);
done:
if (status)
errMessage(status, "dbPutAttribute failure");
return status;
}
int dbIsValueField(const struct dbFldDes *pdbFldDes)
@@ -812,11 +822,10 @@ long dbGet(DBADDR *paddr, short dbrType,
void *pbuffer, long *options, long *nRequest, void *pflin)
{
char *pbuf = pbuffer;
void *pfieldsave;
void *pfieldsave = paddr->pfield;
db_field_log *pfl = (db_field_log *)pflin;
short field_type;
long no_elements;
long offset;
long capacity, no_elements, offset;
struct rset *prset;
long status = 0;
@@ -826,18 +835,33 @@ long dbGet(DBADDR *paddr, short dbrType,
return 0;
if (!pfl || pfl->type == dbfl_type_rec) {
field_type = paddr->field_type;
no_elements = paddr->no_elements;
field_type = paddr->field_type;
no_elements = capacity = paddr->no_elements;
/* Update field info from record
* may modify paddr->pfield
*/
if (paddr->pfldDes->special == SPC_DBADDR &&
(prset = dbGetRset(paddr)) &&
prset->get_array_info) {
status = prset->get_array_info(paddr, &no_elements, &offset);
} else
offset = 0;
} else {
field_type = pfl->field_type;
no_elements = pfl->no_elements;
field_type = pfl->field_type;
no_elements = capacity = pfl->no_elements;
offset = 0;
}
if (field_type >= DBF_INLINK && field_type <= DBF_FWDLINK)
return getLinkValue(paddr, dbrType, pbuf, nRequest);
if (field_type >= DBF_INLINK && field_type <= DBF_FWDLINK) {
status = getLinkValue(paddr, dbrType, pbuf, nRequest);
goto done;
}
if (paddr->special == SPC_ATTRIBUTE)
return getAttrValue(paddr, dbrType, pbuf, nRequest);
if (paddr->special == SPC_ATTRIBUTE) {
status = getAttrValue(paddr, dbrType, pbuf, nRequest);
goto done;
}
/* Check for valid request */
if (INVALID_DB_REQ(dbrType) || field_type > DBF_DEVICE) {
@@ -845,26 +869,13 @@ long dbGet(DBADDR *paddr, short dbrType,
sprintf(message, "dbGet: Request type is %d\n", dbrType);
recGblDbaddrError(S_db_badDbrtype, paddr, message);
return S_db_badDbrtype;
status = S_db_badDbrtype;
goto done;
}
/* For SPC_DBADDR fields, the rset function
* get_array_info() is allowed to modify
* paddr->pfield. So we store the original
* value and restore it later.
*/
pfieldsave = paddr->pfield;
/* Update field info */
if (paddr->pfldDes->special == SPC_DBADDR &&
(prset = dbGetRset(paddr)) &&
prset->get_array_info) {
status = prset->get_array_info(paddr, &no_elements, &offset);
} else
offset = 0;
if (offset == 0 && (!nRequest || no_elements == 1)) {
if (nRequest) *nRequest = 1;
if (nRequest)
*nRequest = 1;
if (!pfl || pfl->type == dbfl_type_rec) {
status = dbFastGetConvertRoutine[field_type][dbrType]
(paddr->pfield, pbuf, paddr);
@@ -883,10 +894,11 @@ long dbGet(DBADDR *paddr, short dbrType,
}
} else {
long n;
long (*convert)();
GETCONVERTFUNC convert;
if (nRequest) {
if (no_elements<(*nRequest)) *nRequest = no_elements;
if (no_elements < *nRequest)
*nRequest = no_elements;
n = *nRequest;
} else {
n = 1;
@@ -901,11 +913,11 @@ long dbGet(DBADDR *paddr, short dbrType,
status = S_db_badDbrtype;
goto done;
}
/* convert database field and place it in the buffer */
/* convert data into the caller's buffer */
if (n <= 0) {
;/*do nothing*/
} else if (!pfl || pfl->type == dbfl_type_rec) {
status = convert(paddr, pbuf, n, no_elements, offset);
status = convert(paddr, pbuf, n, capacity, offset);
} else {
DBADDR localAddr = *paddr; /* Structure copy */
@@ -916,7 +928,7 @@ long dbGet(DBADDR *paddr, short dbrType,
localAddr.pfield = (char *) &pfl->u.v.field;
else
localAddr.pfield = (char *) pfl->u.r.field;
status = convert(&localAddr, pbuf, n, no_elements, offset);
status = convert(&localAddr, pbuf, n, capacity, offset);
}
}
done:
@@ -1228,20 +1240,20 @@ long dbPut(DBADDR *paddr, short dbrType,
status = dbPutConvertRoutine[dbrType][field_type](paddr, pbuffer,
nRequest, no_elements, offset);
}
if (status) goto done;
/* update array info */
if (paddr->pfldDes->special == SPC_DBADDR &&
if (!status &&
paddr->pfldDes->special == SPC_DBADDR &&
prset && prset->put_array_info) {
status = prset->put_array_info(paddr, nRequest);
}
if (status) goto done;
/* check if special processing is required */
/* Always do special processing if needed */
if (special) {
status = dbPutSpecial(paddr,1);
if (status) goto done;
long status2 = dbPutSpecial(paddr, 1);
if (status2) goto done;
}
if (status) goto done;
/* Propagate monitor events for this field, */
/* unless the field is VAL and PP is true. */

View File

@@ -100,7 +100,7 @@ static int dbca_chan_count;
* that has been deleted.
*
* Just a few words about handling dbCaRemoveLink because this is when
* it is essential that nothing trys to use a caLink that has been freed.
* it is essential that nothing tries to use a caLink that has been freed.
*
* dbCaRemoveLink is called when links are being modified. This is only
* done with the dbScan mechanism guranteeing that nothing from
@@ -119,19 +119,16 @@ static int dbca_chan_count;
* dbCaTask issues a ca_clear_channel and then frees the caLink.
*
* If any channel access callback gets called before the ca_clear_channel
* it finds pca->plink=0 and does nothing. Once ca_clear_channel
* it finds pca->plink==0 and does nothing. Once ca_clear_channel
* is called no other callback for this caLink will be called.
*
* dbCaPutLinkCallback causes an additional complication because
* when dbCaRemoveLink is called the callback may not have occured.
* What is done is the following:
* If callback has not occured dbCaRemoveLink sets plinkPutCallback=plink
* If putCallback is called before dbCaTask calls ca_clear_channel
* it does NOT call the users callback.
* dbCaTask calls the users callback passing plinkPutCallback AFTER
* it has called ca_clear_channel
* Thus the users callback will get called exactly once.
*/
* If putComplete sees plink==0 it will not call the user's code.
* If pca->putCallback is non-zero, dbCaTask will call the
* user's callback AFTER it has called ca_clear_channel.
* Thus the user's callback will get called exactly once.
*/
static void addAction(caLink *pca, short link_action)
{
@@ -168,7 +165,7 @@ static void addAction(caLink *pca, short link_action)
static void dbCaLinkFree(caLink *pca)
{
dbCaCallback callback;
struct link *plinkPutCallback = 0;
void *userPvt = 0;
if (pca->chid) {
ca_clear_channel(pca->chid);
@@ -176,8 +173,7 @@ static void dbCaLinkFree(caLink *pca)
}
callback = pca->putCallback;
if (callback) {
plinkPutCallback = pca->plinkPutCallback;
pca->plinkPutCallback = 0;
userPvt = pca->putUserPvt;
pca->putCallback = 0;
pca->putType = 0;
}
@@ -188,12 +184,12 @@ static void dbCaLinkFree(caLink *pca)
free(pca->pvname);
epicsMutexDestroy(pca->lock);
free(pca);
if (callback) callback(plinkPutCallback);
if (callback) callback(userPvt);
}
void dbCaCallbackProcess(void *usrPvt)
void dbCaCallbackProcess(void *userPvt)
{
struct link *plink = (struct link *)usrPvt;
struct link *plink = (struct link *)userPvt;
dbCommon *pdbCommon = plink->value.pv_link.precord;
dbScanLock(pdbCommon);
@@ -223,11 +219,6 @@ void dbCaShutdown(void)
}
}
static void dbCaExit(void *arg)
{
dbCaShutdown();
}
void dbCaLinkInitIsolated(void)
{
if (!workListLock)
@@ -235,7 +226,6 @@ void dbCaLinkInitIsolated(void)
if (!workListEvent)
workListEvent = epicsEventMustCreate(epicsEventEmpty);
dbCaCtl = ctlExit;
epicsAtExit(dbCaExit, NULL);
}
void dbCaLinkInit(void)
@@ -297,8 +287,6 @@ void dbCaRemoveLink(struct link *plink)
epicsMutexMustLock(pca->lock);
pca->plink = 0;
plink->value.pv_link.pvt = 0;
if (pca->putCallback)
pca->plinkPutCallback = plink;
/* Unlock before addAction or dbCaTask might free first */
epicsMutexUnlock(pca->lock);
addAction(pca, CA_CLEAR_CHANNEL);
@@ -800,7 +788,7 @@ static void exceptionCallback(struct exception_handler_args args)
}
}
static void putCallback(struct event_handler_args arg)
static void putComplete(struct event_handler_args arg)
{
caLink *pca = (caLink *)arg.usr;
struct link *plink;
@@ -963,7 +951,7 @@ static void dbCaTask(void *arg)
status = ca_array_put_callback(
pca->dbrType, pca->nelements,
pca->chid, pca->pputNative,
putCallback, pca);
putComplete, pca);
} else {
status = ECA_PUTFAIL;
}
@@ -986,7 +974,7 @@ static void dbCaTask(void *arg)
status = ca_array_put_callback(
DBR_STRING, 1,
pca->chid, pca->pputString,
putCallback, pca);
putComplete, pca);
} else {
status = ECA_PUTFAIL;
}

View File

@@ -63,7 +63,6 @@ typedef struct caLink
short putType;
dbCaCallback putCallback;
void *putUserPvt;
struct link *plinkPutCallback;
/* The following are for access to additional attributes*/
char gotAttributes;
dbCaCallback getAttributes;

View File

@@ -704,21 +704,27 @@ void dbChannelShow(dbChannel *chan, int level, const unsigned short indent)
int pre = ellCount(&chan->pre_chain);
int post = ellCount(&chan->post_chain);
printf("%*schannel name: %s\n", indent, "", chan->name);
printf("%*s field_type=%s (%d bytes), dbr_type=%s, %ld element%s, %d filter%s", indent, "",
dbGetFieldTypeString(chan->addr.field_type), chan->addr.field_size,
dbGetFieldTypeString(chan->addr.dbr_field_type), elems, elems == 1 ? "" : "s",
count, count == 1 ? "" : "s");
if (count)
printf(" (%d pre eventq, %d post eventq)\n", pre, post);
else
printf("\n");
if (level > 0)
dbChannelFilterShow(chan, level - 1, indent + 2);
if (count) {
printf("%*s final field_type=%s (%dB), %ld element%s\n", indent, "",
dbGetFieldTypeString(chan->final_type), chan->final_field_size,
felems, felems == 1 ? "" : "s");
printf("%*sChannel: '%s'\n", indent, "", chan->name);
if (level > 0) {
printf("%*sfield_type=%s (%d bytes), dbr_type=%s, %ld element%s",
indent + 4, "",
dbGetFieldTypeString(chan->addr.field_type),
chan->addr.field_size,
dbGetFieldTypeString(chan->addr.dbr_field_type),
elems, elems == 1 ? "" : "s");
if (count)
printf("\n%*s%d filter%s (%d pre eventq, %d post eventq)\n",
indent + 4, "", count, count == 1 ? "" : "s", pre, post);
else
printf(", no filters\n");
if (level > 1)
dbChannelFilterShow(chan, level - 2, indent + 8);
if (count) {
printf("%*sfinal field_type=%s (%dB), %ld element%s\n", indent + 4, "",
dbGetFieldTypeString(chan->final_type),
chan->final_field_size,
felems, felems == 1 ? "" : "s");
}
}
}

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.
#*************************************************************************
%#include "epicsTypes.h"
%#include "link.h"
@@ -15,59 +15,59 @@
}
field(DESC,DBF_STRING) {
prompt("Descriptor")
promptgroup(GUI_COMMON)
promptgroup("10 - Common")
size(41)
}
field(ASG,DBF_STRING) {
prompt("Access Security Group")
promptgroup(GUI_COMMON)
promptgroup("10 - Common")
special(SPC_AS)
size(29)
}
field(SCAN,DBF_MENU) {
prompt("Scan Mechanism")
promptgroup(GUI_SCAN)
promptgroup("20 - Scan")
special(SPC_SCAN)
interest(1)
menu(menuScan)
}
field(PINI,DBF_MENU) {
prompt("Process at iocInit")
promptgroup(GUI_SCAN)
promptgroup("20 - Scan")
interest(1)
menu(menuPini)
}
field(PHAS,DBF_SHORT) {
prompt("Scan Phase")
promptgroup(GUI_SCAN)
promptgroup("20 - Scan")
special(SPC_SCAN)
interest(1)
}
field(EVNT,DBF_STRING) {
prompt("Event Name")
promptgroup(GUI_SCAN)
promptgroup("20 - Scan")
special(SPC_SCAN)
size(40)
interest(1)
}
field(TSE,DBF_SHORT) {
prompt("Time Stamp Event")
promptgroup(GUI_SCAN)
promptgroup("20 - Scan")
interest(1)
}
field(TSEL,DBF_INLINK) {
prompt("Time Stamp Link")
promptgroup(GUI_SCAN)
promptgroup("20 - Scan")
interest(1)
}
field(DTYP,DBF_DEVICE) {
prompt("Device Type")
promptgroup(GUI_LINKS)
promptgroup("10 - Common")
interest(1)
}
field(DISV,DBF_SHORT) {
prompt("Disable Value")
promptgroup(GUI_SCAN)
promptgroup("20 - Scan")
initial("1")
}
field(DISA,DBF_SHORT) {
@@ -75,7 +75,7 @@
}
field(SDIS,DBF_INLINK) {
prompt("Scanning Disable")
promptgroup(GUI_SCAN)
promptgroup("20 - Scan")
interest(1)
}
%#include "epicsMutex.h"
@@ -131,7 +131,7 @@
}
field(ACKT,DBF_MENU) {
prompt("Alarm Ack Transient")
promptgroup(GUI_ALARMS)
promptgroup("70 - Alarm")
special(SPC_NOMOD)
interest(2)
menu(menuYesNo)
@@ -139,7 +139,7 @@
}
field(DISS,DBF_MENU) {
prompt("Disable Alarm Sevrty")
promptgroup(GUI_SCAN)
promptgroup("70 - Alarm")
interest(1)
menu(menuAlarmSevr)
}
@@ -219,7 +219,7 @@
}
field(PRIO,DBF_MENU) {
prompt("Scheduling Priority")
promptgroup(GUI_SCAN)
promptgroup("20 - Scan")
special(SPC_SCAN)
interest(1)
menu(menuPriority)
@@ -235,14 +235,14 @@
}
field(UDF,DBF_UCHAR) {
prompt("Undefined")
promptgroup(GUI_COMMON)
promptgroup("10 - Common")
pp(TRUE)
interest(1)
initial("1")
}
field(UDFS,DBF_MENU) {
prompt("Undefined Alarm Sevrty")
promptgroup(GUI_COMMON)
promptgroup("70 - Alarm")
interest(1)
menu(menuAlarmSevr)
initial("INVALID")
@@ -256,6 +256,6 @@
}
field(FLNK,DBF_FWDLINK) {
prompt("Forward Process Link")
promptgroup(GUI_LINKS)
promptgroup("20 - Scan")
interest(1)
}

View File

@@ -979,6 +979,7 @@ static void event_task (void *pParm)
{
struct event_user * const evUser = (struct event_user *) pParm;
struct event_que * ev_que;
unsigned char pendexit;
/* init hook */
if (evUser->init_func) {
@@ -1020,9 +1021,10 @@ static void event_task (void *pParm)
event_read (ev_que);
epicsMutexMustLock ( evUser->lock );
}
pendexit = evUser->pendexit;
epicsMutexUnlock ( evUser->lock );
} while ( ! evUser->pendexit );
} while( ! pendexit );
epicsMutexDestroy(evUser->firstque.writelock);

View File

@@ -233,6 +233,17 @@ static void dbtpnCallFunc(const iocshArgBuf *args)
static const iocshFuncDef dbNotifyDumpFuncDef = {"dbNotifyDump",0,0};
static void dbNotifyDumpCallFunc(const iocshArgBuf *args) { dbNotifyDump();}
/* dbPutAttribute */
static const iocshArg dbPutAttrArg0 = { "record type",iocshArgString};
static const iocshArg dbPutAttrArg1 = { "attribute name",iocshArgString};
static const iocshArg dbPutAttrArg2 = { "value",iocshArgString};
static const iocshArg * const dbPutAttrArgs[] =
{&dbPutAttrArg0, &dbPutAttrArg1, &dbPutAttrArg2};
static const iocshFuncDef dbPutAttrFuncDef =
{"dbPutAttribute",3,dbPutAttrArgs};
static void dbPutAttrCallFunc(const iocshArgBuf *args)
{ dbPutAttribute(args[0].sval,args[1].sval,args[2].sval);}
/* tpn */
static const iocshArg tpnArg0 = { "record name",iocshArgString};
static const iocshArg tpnArg1 = { "value",iocshArgString};
@@ -405,6 +416,7 @@ void dbIocRegister(void)
iocshRegister(&pftFuncDef,pftCallFunc);
iocshRegister(&dbtpnFuncDef,dbtpnCallFunc);
iocshRegister(&dbNotifyDumpFuncDef,dbNotifyDumpCallFunc);
iocshRegister(&dbPutAttrFuncDef,dbPutAttrCallFunc);
iocshRegister(&tpnFuncDef,tpnCallFunc);
iocshRegister(&dblsrFuncDef,dblsrCallFunc);
iocshRegister(&dbLockShowLockedFuncDef,dbLockShowLockedCallFunc);

View File

@@ -224,6 +224,7 @@ static long dbDbGetValue(struct link *plink, short dbrType, void *pbuffer,
return S_db_badDbrtype;
if (paddr->no_elements == 1 && (!pnRequest || *pnRequest == 1)
&& paddr->special != SPC_DBADDR
&& paddr->special != SPC_ATTRIBUTE) {
ppv_link->getCvt = dbFastGetConvertRoutine[dbfType][dbrType];
status = ppv_link->getCvt(paddr->pfield, pbuffer, paddr);

View File

@@ -151,7 +151,7 @@ static void buildScanLists(void);
static void addToList(struct dbCommon *precord, scan_list *psl);
static void deleteFromList(struct dbCommon *precord, scan_list *psl);
void scanShutdown(void)
void scanStop(void)
{
int i;
@@ -168,16 +168,16 @@ void scanShutdown(void)
scanOnce((dbCommon *)&exitOnce);
epicsEventWait(startStopEvent);
}
void scanCleanup(void)
{
deletePeriodic();
ioscanDestroy();
epicsRingPointerDelete(onceQ);
epicsEventDestroy(startStopEvent);
epicsEventDestroy(onceSem);
onceSem = startStopEvent = NULL;
free(periodicTaskId);
papPeriodic = NULL;
periodicTaskId = NULL;
@@ -187,7 +187,8 @@ long scanInit(void)
{
int i;
startStopEvent = epicsEventMustCreate(epicsEventEmpty);
if(!startStopEvent)
startStopEvent = epicsEventMustCreate(epicsEventEmpty);
scanCtl = ctlPause;
initPeriodic();
@@ -639,7 +640,8 @@ static void initOnce(void)
if ((onceQ = epicsRingPointerCreate(onceQueueSize)) == NULL) {
cantProceed("initOnce: Ring buffer create failed\n");
}
onceSem = epicsEventMustCreate(epicsEventEmpty);
if(!onceSem)
onceSem = epicsEventMustCreate(epicsEventEmpty);
onceTaskId = epicsThreadCreate("scanOnce",
epicsThreadPriorityScanLow + nPeriodic,
epicsThreadGetStackSize(epicsThreadStackBig), onceTask, 0);

View File

@@ -46,7 +46,8 @@ struct dbCommon;
epicsShareFunc long scanInit(void);
epicsShareFunc void scanRun(void);
epicsShareFunc void scanPause(void);
epicsShareFunc void scanShutdown(void);
epicsShareFunc void scanStop(void);
epicsShareFunc void scanCleanup(void);
epicsShareFunc EVENTPVT eventNameToHandle(const char* event);
epicsShareFunc void postEvent(EVENTPVT epvt);

View File

@@ -334,7 +334,6 @@ long dbpf(const char *pname,const char *pvalue)
{
DBADDR addr;
long status;
epicsUInt16 value;
short dbrType;
size_t n = 1;
@@ -346,16 +345,7 @@ long dbpf(const char *pname,const char *pvalue)
if (nameToAddr(pname, &addr))
return -1;
/* For enumerated types must allow for ENUM rather than string */
/* If entire field is digits then use DBR_ENUM else DBR_STRING */
if (addr.dbr_field_type == DBR_ENUM && *pvalue &&
strspn(pvalue,"0123456789") == strlen(pvalue)) {
sscanf(pvalue, "%hu", &value);
pvalue = (char *) &value;
dbrType = DBR_ENUM;
}
else if (addr.no_elements > 1 &&
if (addr.no_elements > 1 &&
(addr.dbr_field_type == DBR_CHAR || addr.dbr_field_type == DBR_UCHAR)) {
dbrType = addr.dbr_field_type;
n = strlen(pvalue) + 1;

View File

@@ -39,6 +39,7 @@
#include "dbChannel.h"
#include "dbCommon.h"
#include "dbEvent.h"
#include "dbLock.h"
#include "dbNotify.h"
#include "dbStaticLib.h"
#include "recSup.h"
@@ -153,28 +154,30 @@ int dbChannel_get_count(
* in the dbAccess.c dbGet() and getOptions() routines.
*/
dbScanLock(dbChannelRecord(chan));
switch(buffer_type) {
case(oldDBR_STRING):
status = dbChannelGetField(chan, DBR_STRING, pbuffer, &zero, nRequest, pfl);
status = dbChannelGet(chan, DBR_STRING, pbuffer, &zero, nRequest, pfl);
break;
/* case(oldDBR_INT): */
case(oldDBR_SHORT):
status = dbChannelGetField(chan, DBR_SHORT, pbuffer, &zero, nRequest, pfl);
status = dbChannelGet(chan, DBR_SHORT, pbuffer, &zero, nRequest, pfl);
break;
case(oldDBR_FLOAT):
status = dbChannelGetField(chan, DBR_FLOAT, pbuffer, &zero, nRequest, pfl);
status = dbChannelGet(chan, DBR_FLOAT, pbuffer, &zero, nRequest, pfl);
break;
case(oldDBR_ENUM):
status = dbChannelGetField(chan, DBR_ENUM, pbuffer, &zero, nRequest, pfl);
status = dbChannelGet(chan, DBR_ENUM, pbuffer, &zero, nRequest, pfl);
break;
case(oldDBR_CHAR):
status = dbChannelGetField(chan, DBR_CHAR, pbuffer, &zero, nRequest, pfl);
status = dbChannelGet(chan, DBR_CHAR, pbuffer, &zero, nRequest, pfl);
break;
case(oldDBR_LONG):
status = dbChannelGetField(chan, DBR_LONG, pbuffer, &zero, nRequest, pfl);
status = dbChannelGet(chan, DBR_LONG, pbuffer, &zero, nRequest, pfl);
break;
case(oldDBR_DOUBLE):
status = dbChannelGetField(chan, DBR_DOUBLE, pbuffer, &zero, nRequest, pfl);
status = dbChannelGet(chan, DBR_DOUBLE, pbuffer, &zero, nRequest, pfl);
break;
case(oldDBR_STS_STRING):
@@ -187,10 +190,10 @@ int dbChannel_get_count(
} newSt;
options = DBR_STATUS;
status = dbChannelGetField(chan, DBR_STRING, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_STRING, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
status = dbChannelGetField(chan, DBR_STRING, pold->value, &zero,
status = dbChannelGet(chan, DBR_STRING, pold->value, &zero,
nRequest, pfl);
}
break;
@@ -203,10 +206,10 @@ int dbChannel_get_count(
} newSt;
options = DBR_STATUS;
status = dbChannelGetField(chan, DBR_SHORT, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_SHORT, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
status = dbChannelGetField(chan, DBR_SHORT, &pold->value, &zero,
status = dbChannelGet(chan, DBR_SHORT, &pold->value, &zero,
nRequest, pfl);
}
break;
@@ -218,10 +221,10 @@ int dbChannel_get_count(
} newSt;
options = DBR_STATUS;
status = dbChannelGetField(chan, DBR_FLOAT, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_FLOAT, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
status = dbChannelGetField(chan, DBR_FLOAT, &pold->value, &zero,
status = dbChannelGet(chan, DBR_FLOAT, &pold->value, &zero,
nRequest, pfl);
}
break;
@@ -233,10 +236,10 @@ int dbChannel_get_count(
} newSt;
options = DBR_STATUS;
status = dbChannelGetField(chan, DBR_ENUM, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_ENUM, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
status = dbChannelGetField(chan, DBR_ENUM, &pold->value, &zero,
status = dbChannelGet(chan, DBR_ENUM, &pold->value, &zero,
nRequest, pfl);
}
break;
@@ -248,10 +251,10 @@ int dbChannel_get_count(
} newSt;
options = DBR_STATUS;
status = dbChannelGetField(chan, DBR_UCHAR, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_UCHAR, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
status = dbChannelGetField(chan, DBR_UCHAR, &pold->value, &zero,
status = dbChannelGet(chan, DBR_UCHAR, &pold->value, &zero,
nRequest, pfl);
}
break;
@@ -263,10 +266,10 @@ int dbChannel_get_count(
} newSt;
options = DBR_STATUS;
status = dbChannelGetField(chan, DBR_LONG, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_LONG, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
status = dbChannelGetField(chan, DBR_LONG, &pold->value, &zero,
status = dbChannelGet(chan, DBR_LONG, &pold->value, &zero,
nRequest, pfl);
}
break;
@@ -278,11 +281,11 @@ int dbChannel_get_count(
} newSt;
options = DBR_STATUS;
status = dbChannelGetField(chan, DBR_DOUBLE, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_DOUBLE, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
options = 0;
status = dbChannelGetField(chan, DBR_DOUBLE, &pold->value, &options,
status = dbChannelGet(chan, DBR_DOUBLE, &pold->value, &options,
nRequest, pfl);
}
break;
@@ -296,12 +299,12 @@ int dbChannel_get_count(
} newSt;
options = DBR_STATUS | DBR_TIME;
status = dbChannelGetField(chan, DBR_STRING, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_STRING, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->stamp = newSt.time; /* structure copy */
options = 0;
status = dbChannelGetField(chan, DBR_STRING, pold->value, &options,
status = dbChannelGet(chan, DBR_STRING, pold->value, &options,
nRequest, pfl);
}
break;
@@ -315,12 +318,12 @@ int dbChannel_get_count(
} newSt;
options = DBR_STATUS | DBR_TIME;
status = dbChannelGetField(chan, DBR_SHORT, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_SHORT, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->stamp = newSt.time; /* structure copy */
options = 0;
status = dbChannelGetField(chan, DBR_SHORT, &pold->value, &options,
status = dbChannelGet(chan, DBR_SHORT, &pold->value, &options,
nRequest, pfl);
}
break;
@@ -333,12 +336,12 @@ int dbChannel_get_count(
} newSt;
options = DBR_STATUS | DBR_TIME;
status = dbChannelGetField(chan, DBR_FLOAT, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_FLOAT, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->stamp = newSt.time; /* structure copy */
options = 0;
status = dbChannelGetField(chan, DBR_FLOAT, &pold->value, &options,
status = dbChannelGet(chan, DBR_FLOAT, &pold->value, &options,
nRequest, pfl);
}
break;
@@ -351,12 +354,12 @@ int dbChannel_get_count(
} newSt;
options = DBR_STATUS | DBR_TIME;
status = dbChannelGetField(chan, DBR_ENUM, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_ENUM, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->stamp = newSt.time; /* structure copy */
options = 0;
status = dbChannelGetField(chan, DBR_ENUM, &pold->value, &options,
status = dbChannelGet(chan, DBR_ENUM, &pold->value, &options,
nRequest, pfl);
}
break;
@@ -369,12 +372,12 @@ int dbChannel_get_count(
} newSt;
options = DBR_STATUS | DBR_TIME;
status = dbChannelGetField(chan, DBR_CHAR, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_CHAR, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->stamp = newSt.time; /* structure copy */
options = 0;
status = dbChannelGetField(chan, DBR_CHAR, &pold->value, &options,
status = dbChannelGet(chan, DBR_CHAR, &pold->value, &options,
nRequest, pfl);
}
break;
@@ -387,12 +390,12 @@ int dbChannel_get_count(
} newSt;
options = DBR_STATUS | DBR_TIME;
status = dbChannelGetField(chan, DBR_LONG, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_LONG, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->stamp = newSt.time; /* structure copy */
options = 0;
status = dbChannelGetField(chan, DBR_LONG, &pold->value, &options,
status = dbChannelGet(chan, DBR_LONG, &pold->value, &options,
nRequest, pfl);
}
break;
@@ -405,12 +408,12 @@ int dbChannel_get_count(
} newSt;
options = DBR_STATUS | DBR_TIME;
status = dbChannelGetField(chan, DBR_DOUBLE, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_DOUBLE, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->stamp = newSt.time; /* structure copy */
options = 0;
status = dbChannelGetField(chan, DBR_DOUBLE, &pold->value, &options,
status = dbChannelGet(chan, DBR_DOUBLE, &pold->value, &options,
nRequest, pfl);
}
break;
@@ -428,7 +431,7 @@ int dbChannel_get_count(
} newSt;
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG;
status = dbChannelGetField(chan, DBR_SHORT, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_SHORT, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
@@ -440,7 +443,7 @@ int dbChannel_get_count(
pold->lower_warning_limit = newSt.lower_warning_limit;
pold->lower_alarm_limit = newSt.lower_alarm_limit;
options = 0;
status = dbChannelGetField(chan, DBR_SHORT, &pold->value, &options,
status = dbChannelGet(chan, DBR_SHORT, &pold->value, &options,
nRequest, pfl);
}
break;
@@ -457,7 +460,7 @@ int dbChannel_get_count(
options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
DBR_AL_DOUBLE;
status = dbChannelGetField(chan, DBR_FLOAT, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_FLOAT, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->precision = (dbr_short_t) newSt.precision.dp;
@@ -470,7 +473,7 @@ int dbChannel_get_count(
pold->upper_warning_limit = epicsConvertDoubleToFloat(newSt.upper_warning_limit);
pold->lower_warning_limit = epicsConvertDoubleToFloat(newSt.lower_warning_limit);
options = 0;
status = dbChannelGetField(chan, DBR_FLOAT, &pold->value, &options,
status = dbChannelGet(chan, DBR_FLOAT, &pold->value, &options,
nRequest, pfl);
}
break;
@@ -486,7 +489,7 @@ int dbChannel_get_count(
} newSt;
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG;
status = dbChannelGetField(chan, DBR_UCHAR, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_UCHAR, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
@@ -498,7 +501,7 @@ int dbChannel_get_count(
pold->lower_warning_limit = newSt.lower_warning_limit;
pold->lower_alarm_limit = newSt.lower_alarm_limit;
options = 0;
status = dbChannelGetField(chan, DBR_UCHAR, &pold->value, &options,
status = dbChannelGet(chan, DBR_UCHAR, &pold->value, &options,
nRequest, pfl);
}
break;
@@ -513,7 +516,7 @@ int dbChannel_get_count(
} newSt;
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG;
status = dbChannelGetField(chan, DBR_LONG, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_LONG, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
@@ -525,7 +528,7 @@ int dbChannel_get_count(
pold->lower_warning_limit = newSt.lower_warning_limit;
pold->lower_alarm_limit = newSt.lower_alarm_limit;
options = 0;
status = dbChannelGetField(chan, DBR_LONG, &pold->value, &options,
status = dbChannelGet(chan, DBR_LONG, &pold->value, &options,
nRequest, pfl);
}
break;
@@ -542,7 +545,7 @@ int dbChannel_get_count(
options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
DBR_AL_DOUBLE;
status = dbChannelGetField(chan, DBR_DOUBLE, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_DOUBLE, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->precision = (dbr_short_t) newSt.precision.dp;
@@ -555,7 +558,7 @@ int dbChannel_get_count(
pold->lower_warning_limit = newSt.lower_warning_limit;
pold->lower_alarm_limit = newSt.lower_alarm_limit;
options = 0;
status = dbChannelGetField(chan, DBR_DOUBLE, &pold->value, &options,
status = dbChannelGet(chan, DBR_DOUBLE, &pold->value, &options,
nRequest, pfl);
}
break;
@@ -574,7 +577,7 @@ int dbChannel_get_count(
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG |
DBR_AL_LONG;
status = dbChannelGetField(chan, DBR_SHORT, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_SHORT, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
@@ -588,7 +591,7 @@ int dbChannel_get_count(
pold->upper_ctrl_limit = newSt.upper_ctrl_limit;
pold->lower_ctrl_limit = newSt.lower_ctrl_limit;
options = 0;
status = dbChannelGetField(chan, DBR_SHORT, &pold->value, &options,
status = dbChannelGet(chan, DBR_SHORT, &pold->value, &options,
nRequest, pfl);
}
break;
@@ -606,7 +609,7 @@ int dbChannel_get_count(
options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
DBR_CTRL_DOUBLE | DBR_AL_DOUBLE;
status = dbChannelGetField(chan, DBR_FLOAT, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_FLOAT, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->precision = (dbr_short_t) newSt.precision.dp;
@@ -621,7 +624,7 @@ int dbChannel_get_count(
pold->upper_ctrl_limit = epicsConvertDoubleToFloat(newSt.upper_ctrl_limit);
pold->lower_ctrl_limit = epicsConvertDoubleToFloat(newSt.lower_ctrl_limit);
options = 0;
status = dbChannelGetField(chan, DBR_FLOAT, &pold->value, &options,
status = dbChannelGet(chan, DBR_FLOAT, &pold->value, &options,
nRequest, pfl);
}
break;
@@ -638,7 +641,7 @@ int dbChannel_get_count(
memset(pold, '\0', sizeof(struct dbr_ctrl_enum));
/* first get status and severity */
options = DBR_STATUS | DBR_ENUM_STRS;
status = dbChannelGetField(chan, DBR_ENUM, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_ENUM, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
no_str = newSt.no_str;
@@ -648,7 +651,7 @@ int dbChannel_get_count(
strncpy(pold->strs[i], newSt.strs[i], sizeof(pold->strs[i]));
/*now get values*/
options = 0;
status = dbChannelGetField(chan, DBR_ENUM, &pold->value, &options,
status = dbChannelGet(chan, DBR_ENUM, &pold->value, &options,
nRequest, pfl);
}
break;
@@ -665,7 +668,7 @@ int dbChannel_get_count(
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG |
DBR_AL_LONG;
status = dbChannelGetField(chan, DBR_UCHAR, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_UCHAR, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
@@ -679,7 +682,7 @@ int dbChannel_get_count(
pold->upper_ctrl_limit = newSt.upper_ctrl_limit;
pold->lower_ctrl_limit = newSt.lower_ctrl_limit;
options = 0;
status = dbChannelGetField(chan, DBR_UCHAR, &pold->value, &options,
status = dbChannelGet(chan, DBR_UCHAR, &pold->value, &options,
nRequest, pfl);
}
break;
@@ -696,7 +699,7 @@ int dbChannel_get_count(
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG |
DBR_AL_LONG;
status = dbChannelGetField(chan, DBR_LONG, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_LONG, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
@@ -710,7 +713,7 @@ int dbChannel_get_count(
pold->upper_ctrl_limit = newSt.upper_ctrl_limit;
pold->lower_ctrl_limit = newSt.lower_ctrl_limit;
options = 0;
status = dbChannelGetField(chan, DBR_LONG, &pold->value, &options,
status = dbChannelGet(chan, DBR_LONG, &pold->value, &options,
nRequest, pfl);
}
break;
@@ -728,7 +731,7 @@ int dbChannel_get_count(
options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
DBR_CTRL_DOUBLE | DBR_AL_DOUBLE;
status = dbChannelGetField(chan, DBR_DOUBLE, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_DOUBLE, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->precision = (dbr_short_t) newSt.precision.dp;
@@ -743,7 +746,7 @@ int dbChannel_get_count(
pold->upper_ctrl_limit = newSt.upper_ctrl_limit;
pold->lower_ctrl_limit = newSt.lower_ctrl_limit;
options = 0;
status = dbChannelGetField(chan, DBR_DOUBLE, &pold->value, &options,
status = dbChannelGet(chan, DBR_DOUBLE, &pold->value, &options,
nRequest, pfl);
}
break;
@@ -756,13 +759,13 @@ int dbChannel_get_count(
} newSt;
options = DBR_STATUS;
status = dbChannelGetField(chan, DBR_STRING, &newSt, &options, &zero, pfl);
status = dbChannelGet(chan, DBR_STRING, &newSt, &options, &zero, pfl);
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->ackt = newSt.ackt;
pold->acks = newSt.acks;
options = 0;
status = dbChannelGetField(chan, DBR_STRING, pold->value,
status = dbChannelGet(chan, DBR_STRING, pold->value,
&options, nRequest, pfl);
}
break;
@@ -791,8 +794,12 @@ int dbChannel_get_count(
}
break;
default:
return -1;
status = -1;
break;
}
dbScanUnlock(dbChannelRecord(chan));
if (status) return -1;
return 0;
}

View File

@@ -19,7 +19,8 @@
#ifndef INCLdb_field_logh
#define INCLdb_field_logh
#include "epicsTime.h"
#include <epicsTime.h>
#include <epicsTypes.h>
#ifdef __cplusplus
extern "C" {
@@ -32,18 +33,20 @@ extern "C" {
* priority task pending on the event queue wakes up). Strings would slow down
* events for more reasonable size values. DB fields of native type string
* will most likely change infrequently.
*
*
* Strings can be added to the set of types for which updates will be queued
* by defining the macro DB_EVENT_LOG_STRINGS. The code in db_add_event()
* will adjust automatically, it just compares field sizes.
*/
union native_value {
short dbf_int;
short dbf_short;
float dbf_float;
short dbf_enum;
char dbf_char;
long dbf_long;
double dbf_double;
epicsInt8 dbf_char;
epicsInt16 dbf_short;
epicsEnum16 dbf_enum;
epicsInt32 dbf_long;
epicsFloat32 dbf_float;
epicsFloat64 dbf_double;
#ifdef DB_EVENT_LOG_STRINGS
char dbf_string[MAX_STRING_SIZE];
char dbf_string[MAX_STRING_SIZE];
#endif
};

View File

@@ -132,7 +132,7 @@ const char *initHookName(int state)
"initHookAfterInterruptAccept",
"initHookAtEnd"
};
if (state < 0 || state > NELEMENTS(stateName)) {
if (state < 0 || state >= NELEMENTS(stateName)) {
return "Not an initHookState";
}
return stateName[state];

View File

@@ -309,11 +309,11 @@ static void getMaxRangeValues(short field_type, double *pupper_limit,
{
switch(field_type){
case DBF_CHAR:
*pupper_limit = -128.0;
*plower_limit = 127.0;
*pupper_limit = (double) CHAR_MAX;
*plower_limit = (double) CHAR_MIN;
break;
case DBF_UCHAR:
*pupper_limit = 255.0;
*pupper_limit = (double) UCHAR_MAX;
*plower_limit = 0.0;
break;
case DBF_SHORT:

View File

@@ -12,14 +12,17 @@ include $(TOP)/configure/CONFIG
TESTLIBRARY = dbTestIoc
dbTestIoc_SRCS += arrRecord.c
dbTestIoc_SRCS += xRecord.c
dbTestIoc_SRCS += dbLinkdset.c
dbTestIoc_LIBS = dbCore ca Com
TARGETS += $(COMMON_DIR)/dbTestIoc.dbd
DBDDEPENDS_FILES += dbTestIoc.dbd$(DEP)
dbTestIoc_DBD += menuGlobal.dbd
dbTestIoc_DBD += menuConvert.dbd
dbTestIoc_DBD += menuScan.dbd
#dbTestIoc_DBD += arrRecord.dbd
dbTestIoc_DBD += xRecord.dbd
dbTestIoc_DBD += dbLinkdset.dbd
TESTFILES += $(COMMON_DIR)/dbTestIoc.dbd ../xRecord.db
@@ -76,6 +79,7 @@ TESTS += dbCaStatsTest
TESTFILES += ../dbCaStatsTest.db
TARGETS += $(COMMON_DIR)/scanIoTest.dbd
DBDDEPENDS_FILES += scanIoTest.dbd$(DEP)
scanIoTest_DBD += menuGlobal.dbd
scanIoTest_DBD += menuConvert.dbd
scanIoTest_DBD += menuScan.dbd
@@ -95,6 +99,17 @@ dbChannelTest_SRCS += dbTestIoc_registerRecordDeviceDriver.cpp
testHarness_SRCS += dbChannelTest.c
TESTS += dbChannelTest
TARGETS += $(COMMON_DIR)/dbChArrTest.dbd
DBDDEPENDS_FILES += dbChArrTest.dbd$(DEP)
dbChArrTest_DBD += arrRecord.dbd
TESTPROD_HOST += dbChArrTest
dbChArrTest_SRCS += dbChArrTest.cpp
dbChArrTest_SRCS += dbChArrTest_registerRecordDeviceDriver.cpp
testHarness_SRCS += dbChArrTest.cpp
testHarness_SRCS += dbChArrTest_registerRecordDeviceDriver.cpp
TESTFILES += $(COMMON_DIR)/dbChArrTest.dbd ../dbChArrTest.db
TESTS += dbChArrTest
TESTPROD_HOST += chfPluginTest
chfPluginTest_SRCS += chfPluginTest.c
chfPluginTest_SRCS += dbTestIoc_registerRecordDeviceDriver.cpp
@@ -132,7 +147,7 @@ TESTSCRIPTS_HOST += $(TESTS:%=%.t)
include $(TOP)/configure/RULES
arrRecord$(DEP): $(COMMON_DIR)/arrRecord.h
xRecord$(DEP): $(COMMON_DIR)/xRecord.h
dbPutLinkTest$(DEP): $(COMMON_DIR)/xRecord.h
scanIoTest$(DEP): $(COMMON_DIR)/yRecord.h

135
src/ioc/db/test/arrRecord.c Normal file
View File

@@ -0,0 +1,135 @@
/*************************************************************************\
* Copyright (c) 2010 Brookhaven National Laboratory.
* Copyright (c) 2010 Helmholtz-Zentrum Berlin
* fuer Materialien und Energie GmbH.
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* arrRecord.c - minimal array record for test purposes: no processing */
/*
* Author: Ralph Lange <Ralph.Lange@bessy.de>
*
* vaguely implemented like parts of recWaveform.c by Bob Dalesio
*
*/
#include <stdio.h>
#include "dbDefs.h"
#include "epicsPrint.h"
#include "dbAccess.h"
#include "dbEvent.h"
#include "dbFldTypes.h"
#include "recSup.h"
#include "recGbl.h"
#include "cantProceed.h"
#define GEN_SIZE_OFFSET
#include "arrRecord.h"
#undef GEN_SIZE_OFFSET
#include "epicsExport.h"
/* Create RSET - Record Support Entry Table*/
#define report NULL
#define initialize NULL
static long init_record(arrRecord *, int);
static long process(arrRecord *);
#define special NULL
#define get_value NULL
static long cvt_dbaddr(DBADDR *);
static long get_array_info(DBADDR *, long *, long *);
static long put_array_info(DBADDR *, long);
#define get_units NULL
#define get_precision NULL
#define get_enum_str NULL
#define get_enum_strs NULL
#define put_enum_str NULL
#define get_graphic_double NULL
#define get_control_double NULL
#define get_alarm_double NULL
rset arrRSET = {
RSETNUMBER,
report,
initialize,
init_record,
process,
special,
get_value,
cvt_dbaddr,
get_array_info,
put_array_info,
get_units,
get_precision,
get_enum_str,
get_enum_strs,
put_enum_str,
get_graphic_double,
get_control_double,
get_alarm_double
};
epicsExportAddress(rset, arrRSET);
static long init_record(arrRecord *prec, int pass)
{
if (pass == 0) {
if (prec->nelm <= 0)
prec->nelm = 1;
if (prec->ftvl > DBF_ENUM)
prec->ftvl = DBF_UCHAR;
prec->bptr = callocMustSucceed(prec->nelm, dbValueSize(prec->ftvl),
"arr calloc failed");
if (prec->nelm == 1) {
prec->nord = 1;
} else {
prec->nord = 0;
}
return 0;
}
return 0;
}
static long process(arrRecord *prec)
{
return 0;
}
static long cvt_dbaddr(DBADDR *paddr)
{
arrRecord *prec = (arrRecord *) paddr->precord;
paddr->pfield = prec->bptr;
paddr->no_elements = prec->nelm;
paddr->field_type = prec->ftvl;
paddr->field_size = dbValueSize(prec->ftvl);
paddr->dbr_field_type = prec->ftvl;
return 0;
}
static long get_array_info(DBADDR *paddr, long *no_elements, long *offset)
{
arrRecord *prec = (arrRecord *) paddr->precord;
*no_elements = prec->nord;
*offset = prec->off;
return 0;
}
static long put_array_info(DBADDR *paddr, long nNew)
{
arrRecord *prec = (arrRecord *) paddr->precord;
prec->nord = nNew;
if (prec->nord > prec->nelm)
prec->nord = prec->nelm;
return 0;
}

View File

@@ -0,0 +1,34 @@
include "menuGlobal.dbd"
include "menuConvert.dbd"
include "menuScan.dbd"
recordtype(arr) {
include "dbCommon.dbd"
field(VAL, DBF_NOACCESS) {
prompt("Value")
special(SPC_DBADDR)
pp(TRUE)
extra("void *val")
}
field(NELM, DBF_ULONG) {
prompt("Number of Elements")
special(SPC_NOMOD)
initial("1")
}
field(FTVL, DBF_MENU) {
prompt("Field Type of Value")
special(SPC_NOMOD)
menu(menuFtype)
}
field(NORD, DBF_ULONG) {
prompt("Number elements read")
special(SPC_NOMOD)
}
field(OFF, DBF_ULONG) {
prompt("Offset into array")
}
field(BPTR, DBF_NOACCESS) {
prompt("Buffer Pointer")
special(SPC_NOMOD)
extra("void *bptr")
}
}

View File

@@ -99,7 +99,7 @@ MAIN(callbackParallelTest)
myPvt *pcbt[NCALLBACKS];
epicsTimeStamp start;
int noCpus = epicsThreadGetCPUs();
int i, j;
int i, j, slowups, faults;
/* Statistics: min/max/sum/sum^2/n for each priority */
double setupError[NUM_CALLBACK_PRIORITIES][5];
double timeError[NUM_CALLBACK_PRIORITIES][5];
@@ -109,7 +109,7 @@ MAIN(callbackParallelTest)
for (j = 0; j < 5; j++)
setupError[i][j] = timeError[i][j] = defaultError[j];
testPlan(NCALLBACKS * 2 + 1);
testPlan(4);
testDiag("Starting %d parallel callback threads", noCpus);
@@ -138,7 +138,7 @@ MAIN(callbackParallelTest)
pcbt[NCALLBACKS-1]->delay = TEST_DELAY(NCALLBACKS) + 1.0;
pcbt[NCALLBACKS-1]->pass = 0;
testOk1(epicsTimeGetCurrent(&start)==epicsTimeOK);
testOk(epicsTimeGetCurrent(&start)==epicsTimeOK, "Time-of-day clock Ok");
for (i = 0; i < NCALLBACKS ; i++) {
callbackRequest(&pcbt[i]->cb1);
@@ -147,28 +147,43 @@ MAIN(callbackParallelTest)
testDiag("Waiting %.02f sec", pcbt[NCALLBACKS-1]->delay);
epicsEventWait(finished);
slowups = 0;
faults = 0;
for (i = 0; i < NCALLBACKS ; i++) {
if(pcbt[i]->resultFail || pcbt[i]->pass!=2)
testFail("pass = %d for delay = %f", pcbt[i]->pass, pcbt[i]->delay);
testDiag("callback setup fault #%d: pass = %d for delay = %.02f",
++faults, pcbt[i]->pass, pcbt[i]->delay);
else {
double delta = epicsTimeDiffInSeconds(&pcbt[i]->pass1Time, &start);
testOk(fabs(delta) < 0.05, "callback %.02f setup time |%f| < 0.05",
if (fabs(delta) >= 0.05) {
slowups++;
testDiag("callback %.02f setup time |%f| >= 0.05 seconds",
pcbt[i]->delay, delta);
}
updateStats(setupError[i%NUM_CALLBACK_PRIORITIES], delta);
}
}
testOk(faults == 0, "%d faults during callback setup", faults);
testOk(slowups <= 1, "%d slowups during callback setup", slowups);
slowups = 0;
for (i = 0; i < NCALLBACKS ; i++) {
double delta, error;
if(pcbt[i]->resultFail || pcbt[i]->pass!=2)
continue;
delta = epicsTimeDiffInSeconds(&pcbt[i]->pass2Time, &pcbt[i]->pass1Time);
error = delta - pcbt[i]->delay;
testOk(fabs(error) < 0.05, "delay %.02f seconds, callback time error |%.04f| < 0.05",
if (fabs(error) >= 0.05) {
slowups++;
testDiag("delay %.02f seconds, delay error |%.04f| >= 0.05",
pcbt[i]->delay, error);
}
updateStats(timeError[i%NUM_CALLBACK_PRIORITIES], error);
}
testOk(slowups < 5, "%d slowups during callbacks", slowups);
testDiag("Setup time statistics");
printStats(setupError[0], "LOW");
@@ -184,7 +199,8 @@ MAIN(callbackParallelTest)
free(pcbt[i]);
}
callbackShutdown();
callbackStop();
callbackCleanup();
return testDone();
}

View File

@@ -99,7 +99,7 @@ MAIN(callbackTest)
{
myPvt *pcbt[NCALLBACKS];
epicsTimeStamp start;
int i, j;
int i, j, slowups, faults;
/* Statistics: min/max/sum/sum^2/n for each priority */
double setupError[NUM_CALLBACK_PRIORITIES][5];
double timeError[NUM_CALLBACK_PRIORITIES][5];
@@ -109,7 +109,7 @@ MAIN(callbackTest)
for (j = 0; j < 5; j++)
setupError[i][j] = timeError[i][j] = defaultError[j];
testPlan(NCALLBACKS * 2 + 1);
testPlan(4);
callbackInit();
epicsThreadSleep(1.0);
@@ -135,7 +135,7 @@ MAIN(callbackTest)
pcbt[NCALLBACKS-1]->delay = TEST_DELAY(NCALLBACKS) + 1.0;
pcbt[NCALLBACKS-1]->pass = 0;
testOk1(epicsTimeGetCurrent(&start)==epicsTimeOK);
testOk(epicsTimeGetCurrent(&start)==epicsTimeOK, "Time-of-day clock Ok");
for (i = 0; i < NCALLBACKS ; i++) {
callbackRequest(&pcbt[i]->cb1);
@@ -144,28 +144,43 @@ MAIN(callbackTest)
testDiag("Waiting %.02f sec", pcbt[NCALLBACKS-1]->delay);
epicsEventWait(finished);
slowups = 0;
faults = 0;
for (i = 0; i < NCALLBACKS ; i++) {
if(pcbt[i]->resultFail || pcbt[i]->pass!=2)
testFail("pass = %d for delay = %f", pcbt[i]->pass, pcbt[i]->delay);
testDiag("callback setup fault #%d: pass = %d for delay = %.02f",
++faults, pcbt[i]->pass, pcbt[i]->delay);
else {
double delta = epicsTimeDiffInSeconds(&pcbt[i]->pass1Time, &start);
testOk(fabs(delta) < 0.05, "callback %.02f setup time |%f| < 0.05",
if (fabs(delta) >= 0.05) {
slowups++;
testDiag("callback %.02f setup time |%f| >= 0.05 seconds",
pcbt[i]->delay, delta);
}
updateStats(setupError[i%NUM_CALLBACK_PRIORITIES], delta);
}
}
testOk(faults == 0, "%d faults during callback setup", faults);
testOk(slowups <= 1, "%d slowups during callback setup", slowups);
slowups = 0;
for (i = 0; i < NCALLBACKS ; i++) {
double delta, error;
if(pcbt[i]->resultFail || pcbt[i]->pass!=2)
continue;
delta = epicsTimeDiffInSeconds(&pcbt[i]->pass2Time, &pcbt[i]->pass1Time);
error = delta - pcbt[i]->delay;
testOk(fabs(error) < 0.05, "delay %.02f seconds, callback time error |%.04f| < 0.05",
if (fabs(error) >= 0.05) {
slowups++;
testDiag("delay %.02f seconds, delay error |%.04f| >= 0.05",
pcbt[i]->delay, error);
}
updateStats(timeError[i%NUM_CALLBACK_PRIORITIES], error);
}
testOk(slowups < 5, "%d slowups during callbacks", slowups);
testDiag("Setup time statistics");
printStats(setupError[0], "LOW");
@@ -181,7 +196,8 @@ MAIN(callbackTest)
free(pcbt[i]);
}
callbackShutdown();
callbackStop();
callbackCleanup();
return testDone();
}

View File

@@ -418,7 +418,7 @@ static void channelRegisterPost(dbChannel *chan, void *user,
static void channel_report(dbChannel *chan, void *user, int level,
const unsigned short indent)
{
testOk(level == R_LEVEL - 1, "channel_report: level correct");
testOk(level == R_LEVEL - 2, "channel_report: level correct %u == %u", level, R_LEVEL-2);
if (user == puser1) {
testOk(e1 & e_report, "channel_report (1) called");
c1 |= e_report;

View File

@@ -0,0 +1,246 @@
/*************************************************************************\
* Copyright (c) 2010 Brookhaven National Laboratory.
* Copyright (c) 2010 Helmholtz-Zentrum Berlin
* fuer Materialien und Energie GmbH.
* Copyright (c) 2016 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2003 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to the Software License Agreement
* found in the file LICENSE that is included with this distribution.
\*************************************************************************/
/*
* Authors: Ralph Lange <ralph.lange@gmx.de>,
* Andrew Johnson <anj@aps.anl.gov>
*/
#include <stddef.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include "registryFunction.h"
#include "epicsThread.h"
#include "epicsExit.h"
#include "epicsStdio.h"
#include "epicsString.h"
#include "envDefs.h"
#include "dbStaticLib.h"
#include "dbmf.h"
#include "registry.h"
#include "dbAddr.h"
#include "dbAccess.h"
#include "asDbLib.h"
#include "iocInit.h"
#include "iocsh.h"
#include "dbChannel.h"
#include "epicsUnitTest.h"
#include "testMain.h"
#include "osiFileName.h"
extern "C" {
int dbChArrTest_registerRecordDeviceDriver(struct dbBase *pdbbase);
}
#define CA_SERVER_PORT "65535"
const char *server_port = CA_SERVER_PORT;
static void createAndOpen(const char *name, dbChannel**pch)
{
testOk(!!(*pch = dbChannelCreate(name)), "dbChannel %s created", name);
testOk(!(dbChannelOpen(*pch)), "dbChannel opened");
testOk((ellCount(&(*pch)->pre_chain) == 0), "no filters in pre chain");
testOk((ellCount(&(*pch)->post_chain) == 0), "no filters in post chain");
}
extern "C" {
static void freeArray(db_field_log *pfl) {
if (pfl->type == dbfl_type_ref) {
free(pfl->u.r.field);
}
}
}
static void testHead (const char *title, const char *typ = "") {
const char *line = "------------------------------------------------------------------------------";
testDiag("%s", line);
testDiag(title, typ);
testDiag("%s", line);
}
static void check(short dbr_type) {
dbChannel *pch;
db_field_log *pfl;
dbAddr valaddr;
dbAddr offaddr;
const char *offname = NULL, *valname = NULL, *typname = NULL;
epicsInt32 buf[26];
long off, req;
int i;
switch (dbr_type) {
case DBR_LONG:
offname = "i32.OFF";
valname = "i32.VAL";
typname = "long";
break;
case DBR_DOUBLE:
offname = "f64.OFF";
valname = "f64.VAL";
typname = "double";
break;
case DBR_STRING:
offname = "c40.OFF";
valname = "c40.VAL";
typname = "string";
break;
default:
testDiag("Invalid data type %d", dbr_type);
}
(void) dbNameToAddr(offname, &offaddr);
(void) dbNameToAddr(valname, &valaddr);
testHead("Ten %s elements", typname);
/* Fill the record's array field with data, 10..19 */
epicsInt32 ar[10] = {10,11,12,13,14,15,16,17,18,19};
(void) dbPutField(&valaddr, DBR_LONG, ar, 10);
/* Open a channel to it, make sure no filters present */
createAndOpen(valname, &pch);
testOk(pch->final_type == valaddr.field_type,
"final type unchanged (%d->%d)", valaddr.field_type, pch->final_type);
testOk(pch->final_no_elements == valaddr.no_elements,
"final no_elements unchanged (%ld->%ld)", valaddr.no_elements, pch->final_no_elements);
/* TEST1 sets the record's OFF field, then requests 10 elements from the channel,
* passing in a transparent db_field_log and converting the data to LONG on the way in.
* It checks that it got back the expected data and the right number of elements.
*/
#define TEST1(Size, Offset, Text, Expected) \
testDiag("Reading from offset = %d (%s)", Offset, Text); \
off = Offset; req = 10; \
memset(buf, 0, sizeof(buf)); \
(void) dbPutField(&offaddr, DBR_LONG, &off, 1); \
pfl = db_create_read_log(pch); \
testOk(pfl && pfl->type == dbfl_type_rec, "Valid pfl, type = rec"); \
testOk(!dbChannelGetField(pch, DBR_LONG, buf, NULL, &req, pfl), "Got Field value"); \
testOk(req == Size, "Got %ld elements (expected %d)", req, Size); \
if (!testOk(!memcmp(buf, Expected, sizeof(Expected)), "Data correct")) \
for (i=0; i<Size; i++) \
testDiag("Element %d expected %d got %d", i, Expected[i], buf[i]); \
db_delete_field_log(pfl);
const epicsInt32 res_10_0[] = {10,11,12,13,14,15,16,17,18,19};
TEST1(10, 0, "no offset", res_10_0);
const epicsInt32 res_10_4[] = {14,15,16,17,18,19,10,11,12,13};
TEST1(10, 4, "wrapped", res_10_4);
/* Partial array */
testHead("Five %s elements", typname);
off = 0; /* Reset offset for writing the next buffer */
(void) dbPutField(&offaddr, DBR_LONG, &off, 1);
(void) dbPutField(&valaddr, DBR_LONG, &ar[5], 5);
createAndOpen(valname, &pch);
testOk(pch->final_type == valaddr.field_type,
"final type unchanged (%d->%d)", valaddr.field_type, pch->final_type);
testOk(pch->final_no_elements == valaddr.no_elements,
"final no_elements unchanged (%ld->%ld)", valaddr.no_elements, pch->final_no_elements);
const epicsInt32 res_5_0[] = {15,16,17,18,19};
TEST1(5, 0, "no offset", res_5_0);
const epicsInt32 res_5_3[] = {18,19,15,16,17};
TEST1(5, 3, "wrapped", res_5_3);
/* TEST2 sets the record's OFF field, then requests 15 elements from the channel
* but passes in a db_field_log with alternate data, converting that data to LONG.
* It checks that it got back the expected data and the right number of elements.
*/
#define TEST2(Size, Offset, Text, Expected) \
testDiag("Reading from offset = %d (%s)", Offset, Text); \
off = Offset; req = 15; \
memset(buf, 0, sizeof(buf)); \
(void) dbPutField(&offaddr, DBR_LONG, &off, 1); \
pfl = db_create_read_log(pch); \
pfl->type = dbfl_type_ref; \
pfl->field_type = DBF_CHAR; \
pfl->field_size = 1; \
pfl->no_elements = 26; \
pfl->u.r.dtor = freeArray; \
pfl->u.r.field = epicsStrDup("abcdefghijklmnopqrsstuvwxyz"); \
testOk(!dbChannelGetField(pch, DBR_LONG, buf, NULL, &req, pfl), "Got Field value"); \
testOk(req == Size, "Got %ld elements (expected %d)", req, Size); \
if (!testOk(!memcmp(buf, Expected, sizeof(Expected)), "Data correct")) \
for (i=0; i<Size; i++) \
testDiag("Element %d expected '%c' got '%c'", i, Expected[i], buf[i]); \
db_delete_field_log(pfl);
testHead("Fifteen letters from field-log instead of %s", typname);
const epicsInt32 res_15[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o'};
TEST2(15, 0, "no offset", res_15);
TEST2(15, 10, "ignored", res_15);
dbChannelDelete(pch);
}
static dbEventCtx evtctx;
extern "C" {
static void dbChArrTestCleanup(void* junk)
{
dbFreeBase(pdbbase);
registryFree();
pdbbase=0;
db_close_events(evtctx);
dbmfFreeChunks();
}
}
MAIN(dbChArrTest)
{
testPlan(102);
/* Prepare the IOC */
epicsEnvSet("EPICS_CA_SERVER_PORT", server_port);
if (dbReadDatabase(&pdbbase, "dbChArrTest.dbd",
"." OSI_PATH_LIST_SEPARATOR ".." OSI_PATH_LIST_SEPARATOR
"../O.Common" OSI_PATH_LIST_SEPARATOR "O.Common", NULL))
testAbort("Database description not loaded");
dbChArrTest_registerRecordDeviceDriver(pdbbase);
if (dbReadDatabase(&pdbbase, "dbChArrTest.db",
"." OSI_PATH_LIST_SEPARATOR "..", NULL))
testAbort("Test database not loaded");
epicsAtExit(&dbChArrTestCleanup,NULL);
/* Start the IOC */
iocInit();
evtctx = db_init_events();
check(DBR_LONG);
check(DBR_DOUBLE);
check(DBR_STRING);
return testDone();
}

View File

@@ -0,0 +1,15 @@
record(arr, "i32") {
field(DESC, "test array record")
field(NELM, "10")
field(FTVL, "LONG")
}
record(arr, "f64") {
field(DESC, "test array record")
field(NELM, "10")
field(FTVL, "DOUBLE")
}
record(arr, "c40") {
field(DESC, "test array record")
field(NELM, "10")
field(FTVL, "STRING")
}

View File

@@ -242,7 +242,7 @@ MAIN(testDbChannel) /* dbChannelTest is an API routine... */
testOk1(!!(pch = dbChannelCreate("x.{\"scalar\":null}")));
e = e_report;
dbChannelShow(pch, 1, 2);
dbChannelShow(pch, 2, 2);
e = e_close;
if (pch) dbChannelDelete(pch);

View File

@@ -1 +0,0 @@
record(ai, "somename") {}

View File

@@ -165,8 +165,9 @@ typedef struct dbBase {
ELLLIST functionList;
ELLLIST variableList;
ELLLIST bptList;
ELLLIST filterList;
void *pathPvt;
ELLLIST filterList;
ELLLIST guiGroupList;
void *pathPvt;
struct dbPvd *ppvd;
struct gphPvt *pgpHash;
short ignoreMissingMenus;

View File

@@ -73,15 +73,20 @@ static int yyreset(void)
{whitespace} ;
{doublequote}({stringchar}|{escape})*{newline} { /* bad string */
yyerror("Newline in string, closing quote missing");
yyerrorAbort("Newline in string, closing quote missing");
}
. {
char message[40];
YY_BUFFER_STATE *dummy=0;
sprintf(message,"Invalid character '%c'",yytext[0]);
yyerror(message);
if (isprint((int) yytext[0])) {
sprintf(message, "Invalid character '%c'", yytext[0]);
}
else {
sprintf(message, "Invalid character 0x%2.2x", yytext[0]);
}
yyerrorAbort(message);
/*The following suppresses compiler warning messages*/
if(FALSE) yyunput('c',(unsigned char *) message);
if(FALSE) yy_switch_to_buffer(*dummy);

View File

@@ -12,6 +12,7 @@
/*The routines in this module are serially reusable NOT reentrant*/
#include <ctype.h>
#include <epicsStdlib.h>
#include <stddef.h>
#include <stdio.h>
@@ -33,7 +34,6 @@
#include "dbStaticLib.h"
#include "dbStaticPvt.h"
#include "epicsExport.h"
#include "guigroup.h"
#include "link.h"
#include "special.h"
@@ -48,6 +48,9 @@ epicsExportAddress(int,dbRecordsOnceOnly);
epicsShareDef int dbBptNotMonotonic=0;
epicsExportAddress(int,dbBptNotMonotonic);
epicsShareDef int dbQuietMacroWarnings=0;
epicsExportAddress(int,dbQuietMacroWarnings);
/*private routines */
static void yyerrorAbort(char *str);
static void allocTemp(void *pvoid);
@@ -67,6 +70,7 @@ static void dbRecordtypeEmpty(void);
static void dbRecordtypeBody(void);
static void dbRecordtypeFieldHead(char *name,char *type);
static void dbRecordtypeFieldItem(char *name,char *value);
static short findOrAddGuiGroup(const char *name);
static void dbDevice(char *recordtype,char *linktype,
char *dsetname,char *choicestring);
@@ -229,6 +233,7 @@ static long dbReadCOM(DBBASE **ppdbbase,const char *filename, FILE *fp,
free((void *)macPairs);
mac_input_buffer = dbCalloc(MY_BUFFER_SIZE,sizeof(char));
}
macSuppressWarning(macHandle,dbQuietMacroWarnings);
}
pinputFile = dbCalloc(1,sizeof(inputFile));
if(filename) {
@@ -319,10 +324,9 @@ static int db_yyinput(char *buf, int max_size)
if(fgetsRtn) {
int exp = macExpandString(macHandle,mac_input_buffer,
my_buffer,MY_BUFFER_SIZE);
if(exp < 0) {
errPrintf(0,__FILE__, __LINE__,
"macExpandString failed for file %s",
pinputFileNow->filename);
if (exp < 0) {
fprintf(stderr, "Warning: '%s' line %d has undefined macros\n",
pinputFileNow->filename, pinputFileNow->line_num+1);
}
}
} else {
@@ -491,7 +495,23 @@ static void dbRecordtypeFieldHead(char *name,char *type)
yyerrorAbort("Illegal Field Type");
pdbFldDes->field_type = i;
}
static short findOrAddGuiGroup(const char *name)
{
dbGuiGroup *pdbGuiGroup;
GPHENTRY *pgphentry;
pgphentry = gphFind(pdbbase->pgpHash, name, &pdbbase->guiGroupList);
if (!pgphentry) {
pdbGuiGroup = dbCalloc(1,sizeof(dbGuiGroup));
pdbGuiGroup->name = epicsStrDup(name);
ellAdd(&pdbbase->guiGroupList, &pdbGuiGroup->node);
pdbGuiGroup->key = ellCount(&pdbbase->guiGroupList);
pgphentry = gphAdd(pdbbase->pgpHash, pdbGuiGroup->name, &pdbbase->guiGroupList);
pgphentry->userPvt = pdbGuiGroup;
}
return ((dbGuiGroup *)pgphentry->userPvt)->key;
}
static void dbRecordtypeFieldItem(char *name,char *value)
{
dbFldDes *pdbFldDes;
@@ -513,14 +533,7 @@ static void dbRecordtypeFieldItem(char *name,char *value)
return;
}
if(strcmp(name,"promptgroup")==0) {
int i;
for(i=0; i<GUI_NTYPES; i++) {
if(strcmp(value,pamapguiGroup[i].strvalue)==0) {
pdbFldDes->promptgroup = pamapguiGroup[i].value;
return;
}
}
yyerror("Illegal promptgroup. See guigroup.h for legal values");
pdbFldDes->promptgroup = findOrAddGuiGroup(value);
return;
}
if(strcmp(name,"prompt")==0) {

View File

@@ -31,7 +31,6 @@
#include "postfix.h"
#define DBFLDTYPES_GBLSOURCE
#define GUIGROUPS_GBLSOURCE
#define SPECIAL_GBLSOURCE
#define epicsExportSharedSymbols
@@ -41,13 +40,12 @@
#include "dbStaticPvt.h"
#include "devSup.h"
#include "drvSup.h"
#include "guigroup.h"
#include "link.h"
#include "special.h"
int dbStaticDebug = 0;
static char *pNullString = "";
#define messagesize 100
#define messagesize 276
#define RPCL_LEN INFIX_TO_POSTFIX_SIZE(80)
static char *ppstring[5]={"NPP","PP","CA","CP","CPP"};
@@ -417,6 +415,7 @@ dbBase * dbAllocBase(void)
ellInit(&pdbbase->variableList);
ellInit(&pdbbase->bptList);
ellInit(&pdbbase->filterList);
ellInit(&pdbbase->guiGroupList);
gphInitPvt(&pdbbase->pgpHash,256);
dbPvdInitPvt(pdbbase);
return (pdbbase);
@@ -442,8 +441,10 @@ void dbFreeBase(dbBase *pdbbase)
drvSup *pdrvSupNext;
brkTable *pbrkTable;
brkTable *pbrkTableNext;
chFilterPlugin *pfilt;
chFilterPlugin *pfiltNext;
chFilterPlugin *pfilt;
chFilterPlugin *pfiltNext;
dbGuiGroup *pguiGroup;
dbGuiGroup *pguiGroupNext;
int i;
DBENTRY dbentry;
@@ -584,6 +585,15 @@ void dbFreeBase(dbBase *pdbbase)
free(pfilt);
pfilt = pfiltNext;
}
pguiGroup = (dbGuiGroup *)ellFirst(&pdbbase->guiGroupList);
while (pguiGroup) {
pguiGroupNext = (dbGuiGroup *)ellNext(&pguiGroup->node);
gphDelete(pdbbase->pgpHash, pguiGroup->name, &pdbbase->guiGroupList);
ellDelete(&pdbbase->guiGroupList, &pguiGroup->node);
free(pguiGroup->name);
free((void *)pguiGroup);
pguiGroup = pguiGroupNext;
}
gphFreeMem(pdbbase->pgpHash);
dbPvdFreeMem(pdbbase);
dbFreePath(pdbbase);
@@ -604,7 +614,10 @@ DBENTRY * dbAllocEntry(dbBase *pdbbase)
void dbFreeEntry(DBENTRY *pdbentry)
{
if(pdbentry->message) free((void *)pdbentry->message);
if (!pdbentry)
return;
if (pdbentry->message)
free((void *)pdbentry->message);
dbmfFree(pdbentry);
}
@@ -735,6 +748,31 @@ static long dbAddOnePath (DBBASE *pdbbase, const char *path, unsigned length)
return 0;
}
char *dbGetPromptGroupNameFromKey(DBBASE *pdbbase, const short key)
{
dbGuiGroup *pdbGuiGroup;
if (!pdbbase) return NULL;
for (pdbGuiGroup = (dbGuiGroup *)ellFirst(&pdbbase->guiGroupList);
pdbGuiGroup; pdbGuiGroup = (dbGuiGroup *)ellNext(&pdbGuiGroup->node)) {
if (pdbGuiGroup->key == key) return pdbGuiGroup->name;
}
return NULL;
}
short dbGetPromptGroupKeyFromName(DBBASE *pdbbase, const char *name)
{
GPHENTRY *pgphentry;
if (!pdbbase) return 0;
pgphentry = gphFind(pdbbase->pgpHash, name, &pdbbase->guiGroupList);
if (!pgphentry) {
return 0;
} else {
return ((dbGuiGroup*)pgphentry->userPvt)->key;
}
}
long dbWriteRecord(DBBASE *ppdbbase,const char *filename,
const char *precordTypename,int level)
@@ -934,16 +972,11 @@ long dbWriteRecordTypeFP(
fprintf(fp,"\t\tprompt(\"%s\")\n",pdbFldDes->prompt);
if(pdbFldDes->initial)
fprintf(fp,"\t\tinitial(\"%s\")\n",pdbFldDes->initial);
if(pdbFldDes->promptgroup) {
for(j=0; j<GUI_NTYPES; j++) {
if(pamapguiGroup[j].value == pdbFldDes->promptgroup) {
fprintf(fp,"\t\tpromptgroup(%s)\n",
pamapguiGroup[j].strvalue);
break;
}
}
}
if(pdbFldDes->special) {
if (pdbFldDes->promptgroup) {
fprintf(fp,"\t\tpromptgroup(\"%s\")\n",
dbGetPromptGroupNameFromKey(pdbbase, pdbFldDes->promptgroup));
}
if(pdbFldDes->special) {
if(pdbFldDes->special >= SPC_NTYPES) {
fprintf(fp,"\t\tspecial(%d)\n",pdbFldDes->special);
} else for(j=0; j<SPC_NTYPES; j++) {
@@ -1198,7 +1231,7 @@ long dbPutRecordAttribute(
pnew = dbCalloc(1,sizeof(dbRecordAttribute));
if(pattribute) {
ellInsert(&precordType->attributeList,&pattribute->node,
ellInsert(&precordType->attributeList,pattribute->node.previous,
&pnew->node);
} else {
ellAdd(&precordType->attributeList,&pnew->node);
@@ -1226,17 +1259,27 @@ long dbGetAttributePart(DBENTRY *pdbentry, const char **ppname)
const char *pname = *ppname;
dbRecordAttribute *pattribute;
if (!precordType) return S_dbLib_recordTypeNotFound;
if (!precordType)
return S_dbLib_recordTypeNotFound;
pattribute = (dbRecordAttribute *)ellFirst(&precordType->attributeList);
while (pattribute) {
size_t nameLen = strlen(pattribute->name);
int compare = strncmp(pattribute->name, pname, nameLen);
int ch = pname[nameLen];
if (compare == 0 && !(ch == '_' || isalnum(ch))) {
pdbentry->pflddes = pattribute->pdbFldDes;
pdbentry->pfield = pattribute->value;
*ppname = &pname[nameLen];
return 0;
if (compare == 0) {
int ch = pname[nameLen];
if (ch != '_' && !isalnum(ch)) {
/* Any other character can't be in the attribute name */
pdbentry->pflddes = pattribute->pdbFldDes;
pdbentry->pfield = pattribute->value;
*ppname = &pname[nameLen];
return 0;
}
if (strlen(pname) > nameLen) {
compare = -1;
}
}
if (compare >= 0) break;
pattribute = (dbRecordAttribute *)ellNext(&pattribute->node);
@@ -2038,7 +2081,10 @@ long dbPutString(DBENTRY *pdbentry,const char *pstring)
switch (pflddes->field_type) {
case DBF_STRING:
if(!pfield) return(S_dbLib_fieldNotFound);
strncpy((char *)pfield, pstring,pflddes->size);
if(strlen(pstring) >= (size_t)pflddes->size) return S_dbLib_strLen;
strncpy((char *)pfield, pstring, pflddes->size-1);
((char *)pfield)[pflddes->size-1] = 0;
if((pflddes->special == SPC_CALC) && !stringHasMacro) {
char rpcl[RPCL_LEN];
short err;
@@ -2049,7 +2095,6 @@ long dbPutString(DBENTRY *pdbentry,const char *pstring)
calcErrorStr(err), pstring);
}
}
if((short)strlen(pstring) >= pflddes->size) status = S_dbLib_strLen;
break;
case DBF_CHAR:
@@ -3168,14 +3213,9 @@ void dbDumpField(
if(!pdbFldDes->promptgroup) {
printf("\t promptgroup: %d\n",pdbFldDes->promptgroup);
} else {
for(j=0; j<GUI_NTYPES; j++) {
if(pamapguiGroup[j].value == pdbFldDes->promptgroup) {
printf("\t promptgroup: %s\n",
pamapguiGroup[j].strvalue);
break;
}
}
}
printf("\t promptgroup: %s\n",
dbGetPromptGroupNameFromKey(pdbbase, pdbFldDes->promptgroup));
}
printf("\t interest: %hd\n", pdbFldDes->interest);
printf("\t as_level: %d\n",pdbFldDes->as_level);
printf("\t initial: %s\n",

View File

@@ -81,6 +81,10 @@ epicsShareFunc long dbReadDatabaseFP(DBBASE **ppdbbase,
FILE *fp, const char *path, const char *substitutions);
epicsShareFunc long dbPath(DBBASE *pdbbase, const char *path);
epicsShareFunc long dbAddPath(DBBASE *pdbbase, const char *path);
epicsShareFunc char * dbGetPromptGroupNameFromKey(DBBASE *pdbbase,
const short key);
epicsShareFunc short dbGetPromptGroupKeyFromName(DBBASE *pdbbase,
const char *name);
epicsShareFunc long dbWriteRecord(DBBASE *ppdbbase,
const char *filename, const char *precordTypename, int level);
epicsShareFunc long dbWriteRecordFP(DBBASE *ppdbbase,

View File

@@ -42,6 +42,13 @@ typedef struct dbPathNode {
char *directory;
} dbPathNode;
/* Element of the global gui group list */
typedef struct dbGuiGroup {
ELLNODE node;
short key;
char *name;
} dbGuiGroup;
/*The following are in dbPvdLib.c*/
/*directory*/
typedef struct{

View File

@@ -16,68 +16,11 @@
#ifndef __gui_group_h__
#define __gui_group_h__
#define GUI_COMMON 1
#define GUI_ALARMS 2
#define GUI_BITS1 3
#define GUI_BITS2 4
#define GUI_CALC 5
#define GUI_CLOCK 6
#define GUI_COMPRESS 7
#define GUI_CONVERT 8
#define GUI_DISPLAY 9
#define GUI_HIST 10
#define GUI_INPUTS 11
#define GUI_LINKS 12
#define GUI_MBB 13
#define GUI_MOTOR 14
#define GUI_OUTPUT 15
#define GUI_PID 16
#define GUI_PULSE 17
#define GUI_SELECT 18
#define GUI_SEQ1 19
#define GUI_SEQ2 20
#define GUI_SEQ3 21
#define GUI_SUB 22
#define GUI_TIMER 23
#define GUI_WAVE 24
#define GUI_SCAN 25
#define GUI_NTYPES 25
typedef struct mapguiGroup{
char *strvalue;
int value;
}mapguiGroup;
#ifndef GUIGROUPS_GBLSOURCE
extern mapguiGroup pamapguiGroup[];
#else
mapguiGroup pamapguiGroup[GUI_NTYPES] = {
{"GUI_COMMON",GUI_COMMON},
{"GUI_ALARMS",GUI_ALARMS},
{"GUI_BITS1",GUI_BITS1},
{"GUI_BITS2",GUI_BITS2},
{"GUI_CALC",GUI_CALC},
{"GUI_CLOCK",GUI_CLOCK},
{"GUI_COMPRESS",GUI_COMPRESS},
{"GUI_CONVERT",GUI_CONVERT},
{"GUI_DISPLAY",GUI_DISPLAY},
{"GUI_HIST",GUI_HIST},
{"GUI_INPUTS",GUI_INPUTS},
{"GUI_LINKS",GUI_LINKS},
{"GUI_MBB",GUI_MBB},
{"GUI_MOTOR",GUI_MOTOR},
{"GUI_OUTPUT",GUI_OUTPUT},
{"GUI_PID",GUI_PID},
{"GUI_PULSE",GUI_PULSE},
{"GUI_SELECT",GUI_SELECT},
{"GUI_SEQ1",GUI_SEQ1},
{"GUI_SEQ2",GUI_SEQ2},
{"GUI_SEQ3",GUI_SEQ3},
{"GUI_SUB",GUI_SUB},
{"GUI_TIMER",GUI_TIMER},
{"GUI_WAVE",GUI_WAVE},
{"GUI_SCAN",GUI_SCAN}
};
#endif /*GUIGROUPS_GBLSOURCE*/
#error As of Base 3.15.4, the promptgroup implementation has changed. \
This header file (guigroup.h) is invalid and will be removed shortly. \
Instead, you should include dbStaticLib.h, parse the DBD, \
and use dbGetPromptGroupNameFromKey() and dbGetPromptGroupKeyFromName() \
that have been added to dbStaticLib. \
More details in the 3.15.4 release notes and the AppDev Guide.
#endif /*__gui_group_h__*/

View File

@@ -30,7 +30,7 @@ typedef struct rset { /* record support entry table */
RECSUPFUN init_record; /*init record */
RECSUPFUN process; /*process record */
RECSUPFUN special; /*special processing */
RECSUPFUN get_value; /*get value field */
RECSUPFUN get_value; /*no longer used */
RECSUPFUN cvt_dbaddr; /*cvt dbAddr */
RECSUPFUN get_array_info;
RECSUPFUN put_array_info;
@@ -52,21 +52,12 @@ typedef struct rset { /* record support entry table */
#define S_rec_outMem (M_recSup| 3) /*Out of Memory*/
/* Definition os structure for routine get_value */
typedef struct valueDes {
long field_type;
long no_elements;
void * pvalue;
}valueDes;
/************************************************************************
* report(FILE fp,void *precord);
* init();
* init_record(precord,pass);
* process(void *precord);
* special(struct dbAddr *paddr, after);
* get_value(precord,struct valueDes *p);
* cvt_dbaddr(struct dbAddr *paddr);
* get_array_info(paddr,long *no_elements,long *offset);
* put_array_info(paddr,nNew);

View File

@@ -14,8 +14,12 @@ variable(asCaDebug,int)
# Static database access variables
variable(dbRecordsOnceOnly,int)
variable(dbBptNotMonotonic,int)
variable(dbQuietMacroWarnings,int)
# dbLoadTemplate settings
variable(dbTemplateMaxVars,int)
# Default number of parallel callback threads
variable(callbackParallelThreadsDefault,int)
# Real-time operation
variable(dbThreadRealtimeLock,int)

View File

@@ -36,7 +36,7 @@
#include "caeventmask.h"
#define epicsExportSharedSymbols
#include "epicsExport.h" /* defines epicsExportSharedSymbols */
#include "alarm.h"
#include "asDbLib.h"
#include "callback.h"
@@ -86,7 +86,9 @@ static void initDatabase(void);
static void initialProcess(void);
static void exitDatabase(void *dummy);
int dbThreadRealtimeLock = 1;
epicsExportAddress(int, dbThreadRealtimeLock);
/*
* Initialize EPICS on the IOC.
*/
@@ -186,6 +188,10 @@ int iocBuild(void)
rsrv_init();
status = iocBuild_3();
if (dbThreadRealtimeLock)
epicsThreadRealtimeLock();
if (!status) iocBuildMode = buildRSRV;
return status;
}
@@ -607,7 +613,8 @@ static void initialProcess(void)
/*
* Shutdown processing.
* set DB_LINK and CA_LINK to PV_LINK
* Delete record scans
*/
static void doCloseLinks(dbRecordType *pdbRecordType, dbCommon *precord,
void *user)
@@ -678,8 +685,15 @@ int iocShutdown(void)
if (iocState == iocVirgin || iocState == iocStopped) return 0;
iterateRecords(doCloseLinks, NULL);
if (iocBuildMode==buildIsolated) {
scanShutdown();
callbackShutdown();
/* stop and "join" threads */
scanStop();
callbackStop();
}
dbCaShutdown();
if (iocBuildMode==buildIsolated) {
/* free resources */
scanCleanup();
callbackCleanup();
iterateRecords(doFreeRecord, NULL);
dbLockCleanupRecords(pdbbase);
asShutdown();

View File

@@ -7,6 +7,8 @@
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#include "envDefs.h"
#include "epicsVersion.h"
#include "iocsh.h"
#include "libComRegister.h"
@@ -21,10 +23,29 @@
#include "registryIocRegister.h"
#include "rsrvIocRegister.h"
#define quote(v) #v
#define str(v) quote(v)
void iocshRegisterCommon(void)
{
const char *targetArch = envGetConfigParamPtr(&EPICS_BUILD_TARGET_ARCH);
iocshPpdbbase = &pdbbase;
/* This uses a config param so the user can override it */
if (targetArch) {
epicsEnvSet("ARCH", targetArch);
}
/* Base build version variables */
epicsEnvSet("EPICS_VERSION_MAJOR", str(EPICS_VERSION));
epicsEnvSet("EPICS_VERSION_MIDDLE", str(EPICS_REVISION));
epicsEnvSet("EPICS_VERSION_MINOR", str(EPICS_MODIFICATION));
epicsEnvSet("EPICS_VERSION_PATCH", str(EPICS_PATCH_LEVEL));
epicsEnvSet("EPICS_VERSION_SNAPSHOT", EPICS_DEV_SNAPSHOT);
epicsEnvSet("EPICS_VERSION_SITE", EPICS_SITE_VERSION);
epicsEnvSet("EPICS_VERSION_SHORT", EPICS_VERSION_SHORT);
epicsEnvSet("EPICS_VERSION_FULL", EPICS_VERSION_FULL);
dbStaticIocRegister();
registryIocRegister();
dbIocRegister();

View File

@@ -1112,7 +1112,7 @@ unsigned cid
* casAccessRightsCB()
*
* If access right state changes then inform the client.
*
* asLock is held
*/
static void casAccessRightsCB(ASCLIENTPVT ascpvt, asClientStatus type)
{
@@ -1126,7 +1126,7 @@ static void casAccessRightsCB(ASCLIENTPVT ascpvt, asClientStatus type)
pclient = pciu->client;
assert(pclient);
if(pclient == prsrv_cast_client){
if(pclient->proto==IPPROTO_UDP){
return;
}
@@ -1193,7 +1193,7 @@ static void access_rights_reply ( struct channel_in_use * pciu )
int v41;
int status;
assert ( pciu->client != prsrv_cast_client );
assert ( pciu->client->proto!=IPPROTO_UDP );
/*
* noop if this is an old client
@@ -1321,7 +1321,7 @@ static int claim_ciu_action ( caHdrLargeArray *mp,
}
}
else {
epicsMutexMustLock(prsrv_cast_client->chanListLock);
epicsMutexMustLock(client->chanListLock);
/*
* clients which dont claim their
* channel in use block prior to
@@ -1331,7 +1331,7 @@ static int claim_ciu_action ( caHdrLargeArray *mp,
if(!pciu){
errlogPrintf("CAS: client timeout disconnect id=%d\n",
mp->m_cid);
epicsMutexUnlock(prsrv_cast_client->chanListLock);
epicsMutexUnlock(client->chanListLock);
SEND_LOCK(client);
send_err(
mp,
@@ -1342,24 +1342,6 @@ static int claim_ciu_action ( caHdrLargeArray *mp,
return RSRV_ERROR;
}
/*
* duplicate claim message are unacceptable
* (so we disconnect the client)
*/
if (pciu->client!=prsrv_cast_client) {
errlogPrintf("CAS: duplicate claim disconnect id=%d\n",
mp->m_cid);
epicsMutexUnlock(prsrv_cast_client->chanListLock);
SEND_LOCK(client);
send_err(
mp,
ECA_INTERNAL,
client,
"duplicate claim in old connect protocol");
SEND_UNLOCK(client);
return RSRV_ERROR;
}
/*
* remove channel in use block from
* the UDP client where it could time
@@ -1367,9 +1349,9 @@ static int claim_ciu_action ( caHdrLargeArray *mp,
* who is claiming it
*/
ellDelete(
&prsrv_cast_client->chanList,
&client->chanList,
&pciu->node);
epicsMutexUnlock(prsrv_cast_client->chanListLock);
epicsMutexUnlock(client->chanListLock);
epicsMutexMustLock(client->chanListLock);
pciu->state = rsrvCS_pendConnectResp;
@@ -1586,6 +1568,9 @@ static void sendAllUpdateAS ( struct client *client )
else if ( pciu->state == rsrvCS_inServiceUpdatePendAR ) {
access_rights_reply ( pciu );
}
else if ( pciu->state == rsrvCS_shutdown ) {
/* no-op */
}
else {
errlogPrintf (
"%s at %d: corrupt channel state detected durring AR update\n",
@@ -2065,10 +2050,15 @@ static int clear_channel_reply ( caHdrLargeArray *mp,
if ( pciu->state == rsrvCS_inService ||
pciu->state == rsrvCS_pendConnectResp ) {
ellDelete ( &client->chanList, &pciu->node );
pciu->state = rsrvCS_shutdown;
}
else if ( pciu->state == rsrvCS_inServiceUpdatePendAR ||
pciu->state == rsrvCS_pendConnectRespUpdatePendAR ) {
ellDelete ( &client->chanPendingUpdateARList, &pciu->node );
pciu->state = rsrvCS_shutdown;
}
else if ( pciu->state == rsrvCS_shutdown ) {
/* no-op */
}
else {
epicsMutexUnlock( client->chanListLock );
@@ -2515,12 +2505,7 @@ int camessage ( struct client *client )
unsigned bytes_left;
int status = RSRV_ERROR;
if ( ! pCaBucket ) {
pCaBucket = bucketCreate(CAS_HASH_TABLE_SIZE);
if(!pCaBucket){
return RSRV_ERROR;
}
}
assert(pCaBucket);
/* drain remnents of large messages that will not fit */
if ( client->recvBytesToDrain ) {
@@ -2623,7 +2608,7 @@ int camessage ( struct client *client )
if ( CASDEBUG > 2 )
log_header (NULL, client, &msg, pBody, nmsg);
if ( client == prsrv_cast_client ) {
if ( client->proto==IPPROTO_UDP ) {
if ( msg.m_cmmd < NELEMENTS ( udpJumpTable ) ) {
status = ( *udpJumpTable[msg.m_cmmd] )( &msg, pBody, client );
if (status!=RSRV_OK) {

View File

@@ -222,7 +222,7 @@ void cas_send_dg_msg ( struct client * pclient )
/*
* add placeholder for the first version message should it be needed
*/
rsrv_version_reply ( prsrv_cast_client );
rsrv_version_reply ( pclient );
SEND_UNLOCK(pclient);

File diff suppressed because it is too large Load Diff

View File

@@ -54,7 +54,7 @@
/*
* clean_addrq
*/
static void clean_addrq(void)
static void clean_addrq(struct client *client)
{
struct channel_in_use * pciu;
struct channel_in_use * pnextciu;
@@ -67,9 +67,9 @@ static void clean_addrq(void)
epicsTimeGetCurrent ( &current );
epicsMutexMustLock ( prsrv_cast_client->chanListLock );
epicsMutexMustLock ( client->chanListLock );
pnextciu = (struct channel_in_use *)
prsrv_cast_client->chanList.node.next;
client->chanList.node.next;
while( (pciu = pnextciu) ) {
pnextciu = (struct channel_in_use *)pciu->node.next;
@@ -77,7 +77,7 @@ static void clean_addrq(void)
delay = epicsTimeDiffInSeconds(&current,&pciu->time_at_creation);
if (delay > timeout) {
ellDelete(&prsrv_cast_client->chanList, &pciu->node);
ellDelete(&client->chanList, &pciu->node);
LOCK_CLIENTQ;
s = bucketRemoveItemUnsignedId (
pCaBucket,
@@ -96,7 +96,7 @@ static void clean_addrq(void)
if(delay>maxdelay) maxdelay = delay;
}
}
epicsMutexUnlock ( prsrv_cast_client->chanListLock );
epicsMutexUnlock ( client->chanListLock );
# ifdef DEBUG
if(ndelete){
@@ -115,70 +115,19 @@ static void clean_addrq(void)
*/
void cast_server(void *pParm)
{
osiSockAddrNode *paddrNode;
struct sockaddr_in sin;
rsrv_iface_config *conf = pParm;
int status;
int count=0;
int mysocket=0;
struct sockaddr_in new_recv_addr;
osiSocklen_t recv_addr_size;
osiSockIoctl_t nchars;
SOCKET recv_sock, reply_sock;
struct client *client;
recv_addr_size = sizeof(new_recv_addr);
if( IOC_cast_sock!=0 && IOC_cast_sock!=INVALID_SOCKET ) {
epicsSocketDestroy ( IOC_cast_sock );
}
/*
* Open the socket.
* Use ARPA Internet address format and datagram socket.
*/
if ( ( IOC_cast_sock = epicsSocketCreate (AF_INET, SOCK_DGRAM, 0) ) == INVALID_SOCKET ) {
epicsPrintf ("CAS: cast socket creation error\n");
epicsThreadSuspendSelf ();
}
/*
* some concern that vxWorks will run out of mBuf's
* if this change is made
*
* joh 11-10-98
*/
#if 0
{
/*
*
* this allows for faster connects by queuing
* additional incomming UDP search frames
*
* this allocates a 32k buffer
* (uses a power of two)
*/
int size = 1u<<15u;
status = setsockopt (IOC_cast_sock, SOL_SOCKET,
SO_RCVBUF, (char *)&size, sizeof(size));
if (status<0) {
epicsPrintf ("CAS: unable to set cast socket size\n");
}
}
#endif
epicsSocketEnableAddressUseForDatagramFanout ( IOC_cast_sock );
paddrNode = (osiSockAddrNode *) ellFirst ( &casIntfAddrList );
memcpy(&sin, &paddrNode->addr.ia, sizeof (sin));
/* get server's Internet address */
if( bind(IOC_cast_sock, (struct sockaddr *)&sin, sizeof (sin)) < 0){
char sockErrBuf[64];
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
epicsPrintf ("CAS: UDP server port bind error was \"%s\"\n", sockErrBuf );
epicsSocketDestroy ( IOC_cast_sock );
epicsThreadSuspendSelf ();
}
reply_sock = conf->udp;
/*
* setup new client structure but reuse old structure if
@@ -186,27 +135,39 @@ void cast_server(void *pParm)
*
*/
while ( TRUE ) {
prsrv_cast_client = create_client ( IOC_cast_sock, IPPROTO_UDP );
if ( prsrv_cast_client ) {
client = create_client ( reply_sock, IPPROTO_UDP );
if ( client ) {
break;
}
epicsThreadSleep(300.0);
}
if (conf->startbcast) {
recv_sock = conf->udpbcast;
conf->bclient = client;
}
else {
recv_sock = conf->udp;
conf->client = client;
}
client->udpRecv = recv_sock;
casAttachThreadToClient ( prsrv_cast_client );
casAttachThreadToClient ( client );
/*
* add placeholder for the first version message should it be needed
*/
rsrv_version_reply ( prsrv_cast_client );
rsrv_version_reply ( client );
/* these pointers become invalid after signaling casudp_startStopEvent */
conf = NULL;
epicsEventSignal(casudp_startStopEvent);
while (TRUE) {
status = recvfrom (
IOC_cast_sock,
prsrv_cast_client->recv.buf,
prsrv_cast_client->recv.maxstk,
recv_sock,
client->recv.buf,
client->recv.maxstk,
0,
(struct sockaddr *)&new_recv_addr,
&recv_addr_size);
@@ -219,71 +180,90 @@ void cast_server(void *pParm)
sockErrBuf);
epicsThreadSleep(1.0);
}
}
else if (casudp_ctl == ctlRun) {
prsrv_cast_client->recv.cnt = (unsigned) status;
prsrv_cast_client->recv.stk = 0ul;
epicsTimeGetCurrent(&prsrv_cast_client->time_at_last_recv);
prsrv_cast_client->minor_version_number = 0;
prsrv_cast_client->seqNoOfReq = 0;
} else {
size_t idx;
for(idx=0; casIgnoreAddrs[idx]; idx++)
{
if(new_recv_addr.sin_addr.s_addr==casIgnoreAddrs[idx]) {
status = -1; /* ignore */
break;
}
}
}
if (status >= 0 && casudp_ctl == ctlRun) {
client->recv.cnt = (unsigned) status;
client->recv.stk = 0ul;
epicsTimeGetCurrent(&client->time_at_last_recv);
client->minor_version_number = 0;
client->seqNoOfReq = 0;
/*
* If we are talking to a new client flush to the old one
* in case we are holding UDP messages waiting to
* see if the next message is for this same client.
*/
if (prsrv_cast_client->send.stk>sizeof(caHdr)) {
status = memcmp(&prsrv_cast_client->addr,
if (client->send.stk>sizeof(caHdr)) {
status = memcmp(&client->addr,
&new_recv_addr, recv_addr_size);
if(status){
/*
* if the address is different
*/
cas_send_dg_msg(prsrv_cast_client);
prsrv_cast_client->addr = new_recv_addr;
cas_send_dg_msg(client);
client->addr = new_recv_addr;
}
}
else {
prsrv_cast_client->addr = new_recv_addr;
client->addr = new_recv_addr;
}
if (CASDEBUG>1) {
char buf[40];
ipAddrToDottedIP (&prsrv_cast_client->addr, buf, sizeof(buf));
ipAddrToDottedIP (&client->addr, buf, sizeof(buf));
errlogPrintf ("CAS: cast server msg of %d bytes from addr %s\n",
prsrv_cast_client->recv.cnt, buf);
client->recv.cnt, buf);
}
if (CASDEBUG>2)
count = ellCount (&prsrv_cast_client->chanList);
count = ellCount (&client->chanList);
status = camessage ( prsrv_cast_client );
status = camessage ( client );
if(status == RSRV_OK){
if(prsrv_cast_client->recv.cnt !=
prsrv_cast_client->recv.stk){
if(client->recv.cnt !=
client->recv.stk){
char buf[40];
ipAddrToDottedIP (&prsrv_cast_client->addr, buf, sizeof(buf));
ipAddrToDottedIP (&client->addr, buf, sizeof(buf));
epicsPrintf ("CAS: partial (damaged?) UDP msg of %d bytes from %s ?\n",
prsrv_cast_client->recv.cnt-prsrv_cast_client->recv.stk, buf);
client->recv.cnt - client->recv.stk, buf);
epicsTimeToStrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S",
&client->time_at_last_recv);
epicsPrintf ("CAS: message received at %s\n", buf);
}
}
else {
char buf[40];
ipAddrToDottedIP (&prsrv_cast_client->addr, buf, sizeof(buf));
ipAddrToDottedIP (&client->addr, buf, sizeof(buf));
epicsPrintf ("CAS: invalid (damaged?) UDP request from %s ?\n", buf);
epicsTimeToStrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S",
&client->time_at_last_recv);
epicsPrintf ("CAS: message received at %s\n", buf);
}
if (CASDEBUG>2) {
if ( ellCount (&prsrv_cast_client->chanList) ) {
if ( ellCount (&client->chanList) ) {
errlogPrintf ("CAS: Fnd %d name matches (%d tot)\n",
ellCount(&prsrv_cast_client->chanList)-count,
ellCount(&prsrv_cast_client->chanList));
ellCount(&client->chanList)-count,
ellCount(&client->chanList));
}
}
}
@@ -292,15 +272,22 @@ void cast_server(void *pParm)
* allow messages to batch up if more are comming
*/
nchars = 0; /* supress purify warning */
status = socket_ioctl(IOC_cast_sock, FIONREAD, &nchars);
status = socket_ioctl(recv_sock, FIONREAD, &nchars);
if (status<0) {
errlogPrintf ("CA cast server: Unable to fetch N characters pending\n");
cas_send_dg_msg (prsrv_cast_client);
clean_addrq ();
cas_send_dg_msg (client);
clean_addrq (client);
}
else if (nchars == 0) {
cas_send_dg_msg (prsrv_cast_client);
clean_addrq ();
cas_send_dg_msg (client);
clean_addrq (client);
}
}
/* ATM never reached, just a placeholder */
if(!mysocket)
client->sock = INVALID_SOCKET; /* only one cast_server should destroy the reply socket */
destroy_client(client);
epicsSocketDestroy(recv_sock);
}

View File

@@ -35,46 +35,19 @@
#define epicsExportSharedSymbols
#include "server.h"
/*
* forcePort ()
*/
static void forcePort (ELLLIST *pList, unsigned short port)
{
osiSockAddrNode *pNode;
pNode = (osiSockAddrNode *) ellFirst ( pList );
while ( pNode ) {
if ( pNode->addr.sa.sa_family == AF_INET ) {
pNode->addr.ia.sin_port = htons ( port );
}
pNode = (osiSockAddrNode *) ellNext ( &pNode->node );
}
}
/*
* RSRV_ONLINE_NOTIFY_TASK
*/
void rsrv_online_notify_task(void *pParm)
{
unsigned priorityOfSelf = epicsThreadGetPrioritySelf ();
osiSockAddrNode *pNode;
double delay;
double maxdelay;
long longStatus;
double maxPeriod;
caHdr msg;
int status;
SOCKET sock;
int intTrue = TRUE;
unsigned short port;
ca_uint32_t beaconCounter = 0;
char * pStr;
int autoBeaconAddr;
ELLLIST autoAddrList;
char buf[16];
unsigned priorityOfUDP;
epicsThreadBooleanStatus tbs;
epicsThreadId tid;
taskwdInsert (epicsThreadGetIdSelf(),NULL,NULL);
@@ -94,189 +67,34 @@ void rsrv_online_notify_task(void *pParm)
delay = 0.02; /* initial beacon period in sec */
maxdelay = maxPeriod;
/*
* Open the socket.
* Use ARPA Internet address format and datagram socket.
* Format described in <sys/socket.h>.
*/
if ( (sock = epicsSocketCreate (AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
errlogPrintf ("CAS: online socket creation error\n");
epicsThreadSuspendSelf ();
}
status = setsockopt (sock, SOL_SOCKET, SO_BROADCAST,
(char *)&intTrue, sizeof(intTrue));
if (status<0) {
errlogPrintf ("CAS: online socket set up error\n");
epicsThreadSuspendSelf ();
}
{
/*
* this connect is to supress a warning message on Linux
* when we shutdown the read side of the socket. If it
* fails (and it will on old ip kernels) we just ignore
* the failure.
*/
osiSockAddr sockAddr;
sockAddr.ia.sin_family = AF_UNSPEC;
sockAddr.ia.sin_port = htons ( 0 );
sockAddr.ia.sin_addr.s_addr = htonl (0);
connect ( sock, & sockAddr.sa, sizeof ( sockAddr.sa ) );
shutdown ( sock, SHUT_RD );
}
memset((char *)&msg, 0, sizeof msg);
msg.m_cmmd = htons (CA_PROTO_RSRV_IS_UP);
msg.m_count = htons (ca_server_port);
msg.m_dataType = htons (CA_MINOR_PROTOCOL_REVISION);
ellInit ( & beaconAddrList );
ellInit ( & autoAddrList );
pStr = envGetConfigParam(&EPICS_CAS_AUTO_BEACON_ADDR_LIST, sizeof(buf), buf);
if ( ! pStr ) {
pStr = envGetConfigParam(&EPICS_CA_AUTO_ADDR_LIST, sizeof(buf), buf);
}
if (pStr) {
if (strstr(pStr,"no")||strstr(pStr,"NO")) {
autoBeaconAddr = FALSE;
}
else if (strstr(pStr,"yes")||strstr(pStr,"YES")) {
autoBeaconAddr = TRUE;
}
else {
fprintf(stderr,
"CAS: EPICS_CA(S)_AUTO_ADDR_LIST = \"%s\"? Assuming \"YES\"\n", pStr);
autoBeaconAddr = TRUE;
}
}
else {
autoBeaconAddr = TRUE;
}
/*
* load user and auto configured
* broadcast address list
*/
if (envGetConfigParamPtr(&EPICS_CAS_BEACON_PORT)) {
port = envGetInetPortConfigParam (&EPICS_CAS_BEACON_PORT,
(unsigned short) CA_REPEATER_PORT );
}
else {
port = envGetInetPortConfigParam (&EPICS_CA_REPEATER_PORT,
(unsigned short) CA_REPEATER_PORT );
}
/*
* discover beacon addresses associated with this interface
*/
if ( autoBeaconAddr ) {
osiSockAddr addr;
ELLLIST tmpList;
ellInit ( &tmpList );
addr.ia.sin_family = AF_UNSPEC;
osiSockDiscoverBroadcastAddresses (&tmpList, sock, &addr);
forcePort ( &tmpList, port );
removeDuplicateAddresses ( &autoAddrList, &tmpList, 1 );
}
/*
* by default use EPICS_CA_ADDR_LIST for the
* beacon address list
*/
{
const ENV_PARAM *pParam;
if (envGetConfigParamPtr(&EPICS_CAS_INTF_ADDR_LIST) ||
envGetConfigParamPtr(&EPICS_CAS_BEACON_ADDR_LIST)) {
pParam = &EPICS_CAS_BEACON_ADDR_LIST;
}
else {
pParam = &EPICS_CA_ADDR_LIST;
}
/*
* add in the configured addresses
*/
addAddrToChannelAccessAddressList (
&autoAddrList, pParam, port, pParam == &EPICS_CA_ADDR_LIST );
}
removeDuplicateAddresses ( &beaconAddrList, &autoAddrList, 0 );
if ( ellCount ( &beaconAddrList ) == 0 ) {
errlogPrintf ("The CA server's beacon address list was empty after initialization?\n");
}
# ifdef DEBUG
printChannelAccessAddressList (&beaconAddrList);
# endif
tbs = epicsThreadHighestPriorityLevelBelow ( priorityOfSelf, &priorityOfUDP );
if ( tbs != epicsThreadBooleanStatusSuccess ) {
priorityOfUDP = priorityOfSelf;
}
casudp_startStopEvent = epicsEventMustCreate(epicsEventEmpty);
casudp_ctl = ctlPause;
tid = epicsThreadCreate ( "CAS-UDP", priorityOfUDP,
epicsThreadGetStackSize (epicsThreadStackMedium),
cast_server, 0 );
if ( tid == 0 ) {
epicsPrintf ( "CAS: unable to start UDP daemon thread\n" );
}
epicsEventMustWait(casudp_startStopEvent);
epicsEventSignal(beacon_startStopEvent);
while (TRUE) {
pNode = (osiSockAddrNode *) ellFirst (&beaconAddrList);
while (pNode) {
char buf[64];
ELLNODE *cur;
status = connect (sock, &pNode->addr.sa,
sizeof(pNode->addr.sa));
if (status<0) {
/* send beacon to each interface */
for(cur=ellFirst(&beaconAddrList); cur; cur=ellNext(cur))
{
osiSockAddrNode *pAddr = CONTAINER(cur, osiSockAddrNode, node);
status = sendto (beaconSocket, (char *)&msg, sizeof(msg), 0,
&pAddr->addr.sa, sizeof(pAddr->addr));
if (status < 0) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString (
sockErrBuf, sizeof ( sockErrBuf ) );
ipAddrToDottedIP (&pNode->addr.ia, buf, sizeof(buf));
errlogPrintf ( "%s: CA beacon routing (connect to \"%s\") error was \"%s\"\n",
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
ipAddrToDottedIP (&pAddr->addr.ia, buf, sizeof(buf));
errlogPrintf ( "%s: CA beacon (send to \"%s\") error was \"%s\"\n",
__FILE__, buf, sockErrBuf);
}
else {
struct sockaddr_in if_addr;
osiSocklen_t size = sizeof (if_addr);
status = getsockname (sock, (struct sockaddr *) &if_addr, &size);
if (status<0) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
errlogPrintf ( "%s: CA beacon routing (getsockname) error was \"%s\"\n",
__FILE__, sockErrBuf);
}
else if (if_addr.sin_family==AF_INET) {
msg.m_available = if_addr.sin_addr.s_addr;
msg.m_cid = htonl ( beaconCounter );
status = send (sock, (char *)&msg, sizeof(msg), 0);
if (status < 0) {
char sockErrBuf[64];
epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
ipAddrToDottedIP (&pNode->addr.ia, buf, sizeof(buf));
errlogPrintf ( "%s: CA beacon (send to \"%s\") error was \"%s\"\n",
__FILE__, buf, sockErrBuf);
}
else {
assert (status == sizeof(msg));
}
}
assert (status == sizeof(msg));
}
pNode = (osiSockAddrNode *) pNode->node.next;
}
epicsThreadSleep(delay);
@@ -287,7 +105,7 @@ void rsrv_online_notify_task(void *pParm)
}
}
beaconCounter++; /* expected to overflow */
msg.m_cid = htonl ( beaconCounter++ ); /* expected to overflow */
while (beacon_ctl == ctlPause) {
epicsThreadSleep(0.1);

View File

@@ -32,6 +32,7 @@
#include "ellLib.h"
#include "epicsTime.h"
#include "epicsAssert.h"
#include "osiSock.h"
#ifdef rsrvRestore_epicsExportSharedSymbols
#define epicsExportSharedSymbols
@@ -88,7 +89,7 @@ typedef struct client {
char *pUserName;
char *pHostName;
epicsEventId blockSem; /* used whenever the client blocks */
SOCKET sock;
SOCKET sock, udpRecv;
int proto;
epicsThreadId tid;
unsigned minor_version_number;
@@ -98,12 +99,25 @@ typedef struct client {
char disconnect; /* disconnect detected */
} client;
/* Channel state shows which struct client list a
* channel_in_us::node is in.
*
* client::chanList
* rsrvCS_pendConnectResp, rsrvCS_inService
* client::chanPendingUpdateARList
* rsrvCS_pendConnectRespUpdatePendAR, rsrvCS_inServiceUpdatePendAR
* Not in any list
* rsrvCS_shutdown
*
* rsrvCS_invalid is not used
*/
enum rsrvChanState {
rsrvCS_invalid,
rsrvCS_pendConnectResp,
rsrvCS_inService,
rsrvCS_pendConnectRespUpdatePendAR,
rsrvCS_inServiceUpdatePendAR
rsrvCS_inServiceUpdatePendAR,
rsrvCS_shutdown
};
/*
@@ -137,6 +151,16 @@ struct event_ext {
char modified; /* mod & ev flw ctrl enbl */
};
typedef struct {
ELLNODE node;
osiSockAddr tcpAddr, /* TCP listener endpoint */
udpAddr, /* UDP name unicast receiver endpoint */
udpbcastAddr; /* UDP name broadcast receiver endpoint */
SOCKET tcp, udp, udpbcast;
struct client *client, *bclient;
unsigned int startbcast:1;
} rsrv_iface_config;
enum ctl {ctlInit, ctlRun, ctlPause, ctlExit};
@@ -160,15 +184,16 @@ enum ctl {ctlInit, ctlRun, ctlPause, ctlExit};
#endif
GLBLTYPE int CASDEBUG;
GLBLTYPE SOCKET IOC_sock;
GLBLTYPE SOCKET IOC_cast_sock;
GLBLTYPE unsigned short ca_server_port;
GLBLTYPE ELLLIST clientQ; /* locked by clientQlock */
GLBLTYPE unsigned short ca_server_port, ca_udp_port, ca_beacon_port;
GLBLTYPE ELLLIST clientQ; /* (TCP clients) locked by clientQlock */
GLBLTYPE ELLLIST clientQudp; /* locked by clientQlock */
GLBLTYPE ELLLIST servers; /* rsrv_iface_config::node, read-only after rsrv_init() */
GLBLTYPE ELLLIST beaconAddrList;
GLBLTYPE ELLLIST casIntfAddrList;
GLBLTYPE SOCKET beaconSocket;
GLBLTYPE ELLLIST casIntfAddrList, casMCastAddrList;
GLBLTYPE epicsUInt32 *casIgnoreAddrs;
GLBLTYPE epicsMutexId clientQlock;
GLBLTYPE struct client *prsrv_cast_client;
GLBLTYPE BUCKET *pCaBucket;
GLBLTYPE BUCKET *pCaBucket; /* locked by clientQlock */
GLBLTYPE void *rsrvClientFreeList;
GLBLTYPE void *rsrvChanFreeList;
GLBLTYPE void *rsrvEventFreeList;
@@ -176,7 +201,7 @@ GLBLTYPE void *rsrvSmallBufFreeListTCP;
GLBLTYPE void *rsrvLargeBufFreeListTCP;
GLBLTYPE unsigned rsrvSizeofLargeBufTCP;
GLBLTYPE void *rsrvPutNotifyFreeList;
GLBLTYPE unsigned rsrvChannelCount;
GLBLTYPE unsigned rsrvChannelCount; /* locked by clientQlock */
GLBLTYPE epicsEventId casudp_startStopEvent;
GLBLTYPE epicsEventId beacon_startStopEvent;
@@ -185,6 +210,7 @@ GLBLTYPE volatile enum ctl casudp_ctl;
GLBLTYPE volatile enum ctl beacon_ctl;
GLBLTYPE volatile enum ctl castcp_ctl;
GLBLTYPE unsigned int threadPrios[5];
#define CAS_HASH_TABLE_SIZE 4096

View File

@@ -45,6 +45,11 @@ Com_SYS_LIBS_WIN32 = ws2_32 advapi32 user32
Com_RCS = Com.rc
ifeq ($(T_A),$(EPICS_HOST_ARCH))
# Antelope & flex are needed to finish libCom
DELAY_INSTALL_LIBS = YES
endif
include $(TOP)/configure/RULES
include $(LIBCOM)/as/RULES

View File

@@ -529,6 +529,12 @@ Init (rtems_task_argument ignored)
putenv ("TERM=xterm");
putenv ("IOCSH_HISTSIZE=20");
/*
* Display some OS information
*/
printf("\n***** RTEMS Version: %s *****\n",
rtems_get_version_string());
/*
* Start network
*/

View File

@@ -486,7 +486,7 @@ epicsShareFunc int epicsShareAPI bucketShow(BUCKET *pb)
unsigned count;
unsigned maxEntries;
printf( "Bucket entries in use = %d bytes in use = %ld\n",
printf( " Bucket entries in use = %d bytes in use = %ld\n",
pb->nInUse,
(long) (sizeof(*pb)+(pb->hashIdMask+1)*
sizeof(ITEM *)+pb->nInUse*sizeof(ITEM)));
@@ -511,7 +511,7 @@ epicsShareFunc int epicsShareAPI bucketShow(BUCKET *pb)
mean = X/nElem;
stdDev = sqrt(XX/nElem - mean*mean);
printf( "Bucket entries/hash id - mean = %f std dev = %f max = %d\n",
printf( " Bucket entries/hash id - mean = %f std dev = %f max = %d\n",
mean,
stdDev,
maxEntries);

View File

@@ -33,6 +33,10 @@ static int cond_search(const char **ppinst, int match);
#define PI 3.14159265358979323
#endif
/* Turn off global optimization for 64-bit MSVC builds */
#if defined(_WIN32) && defined(_M_X64) && !defined(_MINGW)
# pragma optimize("g", off)
#endif
/* calcPerform
*
@@ -45,6 +49,7 @@ epicsShareFunc long
double *ptop; /* stack pointer */
double top; /* value from top of stack */
epicsInt32 itop; /* integer from top of stack */
epicsUInt32 utop; /* unsigned integer from top of stack */
int op;
int nargs;
@@ -150,7 +155,7 @@ epicsShareFunc long
break;
case ABS_VAL:
if (*ptop < 0.0) *ptop = - *ptop;
*ptop = fabs(*ptop);
break;
case EXP:
@@ -262,7 +267,7 @@ epicsShareFunc long
case NINT:
top = *ptop;
*ptop = (double)(epicsInt32)(top >= 0 ? top + 0.5 : top - 0.5);
*ptop = (epicsInt32) (top >= 0 ? top + 0.5 : top - 0.5);
break;
case RANDOM:
@@ -283,34 +288,45 @@ epicsShareFunc long
*ptop = ! *ptop;
break;
/* For bitwise operations on values with bit 31 set, double values
* must first be cast to unsigned to correctly set that bit; the
* double value must be negative in that case. The result must be
* cast to a signed integer before converting to the double result.
*/
case BIT_OR:
itop = (epicsInt32) *ptop--;
*ptop = (epicsInt32) *ptop | itop;
utop = *ptop--;
*ptop = (epicsInt32) ((epicsUInt32) *ptop | utop);
break;
case BIT_AND:
itop = (epicsInt32) *ptop--;
*ptop = (epicsInt32) *ptop & itop;
utop = *ptop--;
*ptop = (epicsInt32) ((epicsUInt32) *ptop & utop);
break;
case BIT_EXCL_OR:
itop = (epicsInt32) *ptop--;
*ptop = (epicsInt32) *ptop ^ itop;
utop = *ptop--;
*ptop = (epicsInt32) ((epicsUInt32) *ptop ^ utop);
break;
case BIT_NOT:
itop = (epicsInt32) *ptop;
*ptop = ~itop;
utop = *ptop;
*ptop = (epicsInt32) ~utop;
break;
/* The shift operators use signed integers, so a right-shift will
* extend the sign bit into the left-hand end of the value. The
* double-casting through unsigned here is important, see above.
*/
case RIGHT_SHIFT:
itop = (epicsInt32) *ptop--;
*ptop = (epicsInt32) *ptop >> itop;
utop = *ptop--;
*ptop = ((epicsInt32) (epicsUInt32) *ptop) >> (utop & 31);
break;
case LEFT_SHIFT:
itop = (epicsInt32) *ptop--;
*ptop = (epicsInt32) *ptop << itop;
utop = *ptop--;
*ptop = ((epicsInt32) (epicsUInt32) *ptop) << (utop & 31);
break;
case NOT_EQ:
@@ -367,6 +383,9 @@ epicsShareFunc long
*presult = *ptop;
return 0;
}
#if defined(_WIN32) && defined(_M_X64) && !defined(_MINGW)
# pragma optimize("", on)
#endif
epicsShareFunc long

View File

@@ -251,7 +251,7 @@ epicsShareFunc long
goto bad;
}
psrc = pnext;
lit_i = (int) lit_d;
lit_i = (epicsInt32) lit_d;
if (lit_d != (double) lit_i) {
*pout++ = pel->code;
memcpy(pout, &lit_d, sizeof(double));
@@ -272,8 +272,8 @@ epicsShareFunc long
}
psrc = pnext;
*pout++ = LITERAL_INT;
memcpy(pout, &lit_ui, sizeof(epicsInt32));
pout += sizeof(epicsInt32);
memcpy(pout, &lit_ui, sizeof(epicsUInt32));
pout += sizeof(epicsUInt32);
}
operand_needed = FALSE;

View File

@@ -52,9 +52,9 @@ void SingletonUntyped :: incrRefCount ( PBuild pBuild )
void SingletonUntyped :: decrRefCount ( PDestroy pDestroy )
{
assert ( _refCount > 0 );
epicsGuard < epicsMutex >
guard ( *pEPICSSigletonMutex );
assert ( _refCount > 0 );
_refCount--;
if ( _refCount == 0 ) {
( *pDestroy ) ( _pInstance );

View File

@@ -8,5 +8,7 @@
# This is a Makefile fragment, see src/libCom/Makefile.
envData.c: $(LIBCOM)/env/envDefs.h $(LIBCOM)/env/bldEnvData.pl \
$(CONFIG)/CONFIG_ENV $(CONFIG)/CONFIG_SITE_ENV
$(PERL) $(LIBCOM)/env/bldEnvData.pl $(INSTALL_QUIETLY) $(CONFIG)
$(CONFIG)/CONFIG_ENV $(CONFIG)/CONFIG_SITE_ENV \
$(wildcard $(CONFIG)/os/CONFIG_SITE_ENV.$(T_A))
$(PERL) $(LIBCOM)/env/bldEnvData.pl $(INSTALL_QUIETLY) -t $(T_A) \
-c $(CMPLR_CLASS) -s $(OS_CLASS) $(CONFIG)

View File

@@ -26,13 +26,13 @@ use Text::Wrap;
my $tool = basename($0);
our ($opt_h, $opt_q);
our ($opt_h, $opt_q, $opt_t, $opt_s, $opt_c);
our $opt_o = 'envData.c';
$Getopt::Std::OUTPUT_HELP_VERSION = 1;
$Text::Wrap::columns = 75;
&HELP_MESSAGE unless getopts('ho:q') && @ARGV == 1;
&HELP_MESSAGE unless getopts('ho:qt:s:c:') && @ARGV == 1;
&HELP_MESSAGE if $opt_h;
my $config = AbsPath(shift);
@@ -52,16 +52,31 @@ while (<SRC>) {
}
close SRC;
# Read the values from the CONFIG_ENV and CONFIG_SITE_ENV files
# A list of configure/CONFIG_* files to read
#
my $config_env = "$config/CONFIG_ENV";
my $config_site_env = "$config/CONFIG_SITE_ENV";
my @configs = ("$config/CONFIG_ENV", "$config/CONFIG_SITE_ENV");
my %values;
readReleaseFiles($config_env, \%values);
readReleaseFiles($config_site_env, \%values);
if ($opt_t) {
my $config_arch_env = "$config/os/CONFIG_SITE_ENV.$opt_t";
push @configs, $config_arch_env
if -f $config_arch_env;
}
# Warn about any vars with no value
my @sources = ($env_defs, @configs);
# Get values from the config files
#
my (%values, @dummy);
readRelease($_, \%values, \@dummy) foreach @configs;
expandRelease(\%values);
# Get values from the command-line
#
$values{EPICS_BUILD_COMPILER_CLASS} = $opt_c if $opt_c;
$values{EPICS_BUILD_OS_CLASS} = $opt_s if $opt_s;
$values{EPICS_BUILD_TARGET_ARCH} = $opt_t if $opt_t;
# Warn about vars with no configured value
#
my @undefs = grep {!exists $values{$_}} @vars;
warn "$tool: No value given for $_\n" foreach @undefs;
@@ -73,13 +88,13 @@ print "Generating $opt_o\n" unless $opt_q;
open OUT, '>', $opt_o
or die "$tool: Cannot create $opt_o: $!\n";
my $sources = join "\n", map {" * $_"} @sources;
print OUT << "END";
/* Generated file $opt_o
*
* Created from
* $env_defs
* $config_env
* $config_site_env
$sources
*/
#include <stddef.h>
@@ -88,18 +103,23 @@ print OUT << "END";
END
# Define all parameters, giving variable name and default value
# Define a default value for each named parameter
#
foreach my $var (@vars) {
my $default = $values{$var} || '';
$default =~ s/^"//;
$default =~ s/"$//;
my $default = $values{$var};
if (defined $default) {
$default =~ s/^"//;
$default =~ s/"$//;
}
else {
$default = '';
}
print OUT "epicsShareDef const ENV_PARAM $var =\n",
" {\"$var\", \"$default\"};\n";
}
# Now create a list of all those parameters
# Also provide a list of all defined parameters
#
print OUT "\n",
"epicsShareDef const ENV_PARAM* env_param_list[] = {\n",
@@ -112,6 +132,9 @@ sub HELP_MESSAGE {
" -h Help: Print this message\n",
" -q Quiet: Only print errors\n",
" -o file Output filename, default is $opt_o\n",
" -t arch Target architecture \$(T_A) name\n",
" -s os Operating system \$(OS_CLASS)\n",
" -c comp Compiler class \$(CMPLR_CLASS)\n",
"\n";
exit 1;

View File

@@ -40,7 +40,7 @@ typedef struct envParam {
} ENV_PARAM;
/*
* bldEnvData looks for "epicsShareExtern const ENV_PARAM"
* bldEnvData.pl looks for "epicsShareExtern const ENV_PARAM <name>;"
*/
epicsShareExtern const ENV_PARAM EPICS_CA_ADDR_LIST;
epicsShareExtern const ENV_PARAM EPICS_CA_CONN_TMO;
@@ -58,6 +58,9 @@ epicsShareExtern const ENV_PARAM EPICS_CAS_SERVER_PORT;
epicsShareExtern const ENV_PARAM EPICS_CA_BEACON_PERIOD; /* deprecated */
epicsShareExtern const ENV_PARAM EPICS_CAS_BEACON_PERIOD;
epicsShareExtern const ENV_PARAM EPICS_CAS_BEACON_PORT;
epicsShareExtern const ENV_PARAM EPICS_BUILD_COMPILER_CLASS;
epicsShareExtern const ENV_PARAM EPICS_BUILD_OS_CLASS;
epicsShareExtern const ENV_PARAM EPICS_BUILD_TARGET_ARCH;
epicsShareExtern const ENV_PARAM EPICS_TIMEZONE;
epicsShareExtern const ENV_PARAM EPICS_TS_NTP_INET;
epicsShareExtern const ENV_PARAM EPICS_IOC_LOG_PORT;
@@ -88,6 +91,8 @@ epicsShareFunc long epicsShareAPI
envGetLongConfigParam(const ENV_PARAM *pParam, long *pLong);
epicsShareFunc unsigned short epicsShareAPI envGetInetPortConfigParam
(const ENV_PARAM *pEnv, unsigned short defaultPort);
epicsShareFunc long epicsShareAPI
envGetBoolConfigParam(const ENV_PARAM *pParam, int *pBool);
epicsShareFunc long epicsShareAPI epicsPrtEnvParams(void);
epicsShareFunc void epicsShareAPI epicsEnvSet (const char *name, const char *value);
epicsShareFunc void epicsShareAPI epicsEnvShow (const char *name);

View File

@@ -43,6 +43,7 @@
#define epicsExportSharedSymbols
#include "epicsStdlib.h"
#include "epicsStdio.h"
#include "epicsString.h"
#include "errMdef.h"
#include "errlog.h"
#include "envDefs.h"
@@ -319,7 +320,19 @@ long *pLong /* O pointer to place to store value */
}
return -1;
}
long epicsShareAPI
envGetBoolConfigParam(const ENV_PARAM *pParam, int *pBool)
{
char text[20];
if(!envGetConfigParam(pParam, sizeof(text), text))
return -1;
*pBool = epicsStrCaseCmp(text, "yes")==0;
return 0;
}
/*+/subr**********************************************************************
* NAME envPrtConfigParam - print value of a configuration parameter
*

View File

@@ -120,10 +120,12 @@ epicsShareFunc int errlogPrintf(const char *pFormat, ...)
isOkToBlock = epicsThreadIsOkToBlock();
if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) {
FILE *console = pvtData.console ? pvtData.console : stderr;
va_start(pvar, pFormat);
nchar = vfprintf(pvtData.console, pFormat, pvar);
nchar = vfprintf(console, pFormat, pvar);
va_end (pvar);
fflush(pvtData.console);
fflush(console);
}
if (pvtData.atExit)
@@ -146,6 +148,7 @@ epicsShareFunc int errlogVprintf(
int nchar;
char *pbuffer;
int isOkToBlock;
FILE *console;
if (epicsInterruptIsInterruptContext()) {
epicsInterruptContextMessage
@@ -160,15 +163,17 @@ epicsShareFunc int errlogVprintf(
pbuffer = msgbufGetFree(isOkToBlock);
if (!pbuffer) {
vfprintf(pvtData.console, pFormat, pvar);
fflush(pvtData.console);
console = pvtData.console ? pvtData.console : stderr;
vfprintf(console, pFormat, pvar);
fflush(console);
return 0;
}
nchar = tvsnPrint(pbuffer, pvtData.maxMsgSize, pFormat?pFormat:"", pvar);
if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) {
fprintf(pvtData.console, "%s", pbuffer);
fflush(pvtData.console);
console = pvtData.console ? pvtData.console : stderr;
fprintf(console, "%s", pbuffer);
fflush(console);
}
msgbufSetSize(nchar);
return nchar;
@@ -243,11 +248,13 @@ epicsShareFunc int errlogSevPrintf(
isOkToBlock = epicsThreadIsOkToBlock();
if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) {
fprintf(pvtData.console, "sevr=%s ", errlogGetSevEnumString(severity));
FILE *console = pvtData.console ? pvtData.console : stderr;
fprintf(console, "sevr=%s ", errlogGetSevEnumString(severity));
va_start(pvar, pFormat);
vfprintf(pvtData.console, pFormat, pvar);
vfprintf(console, pFormat, pvar);
va_end(pvar);
fflush(pvtData.console);
fflush(console);
}
va_start(pvar, pFormat);
@@ -359,7 +366,9 @@ epicsShareFunc int epicsShareAPI errlogRemoveListeners(
epicsMutexUnlock(pvtData.listenerLock);
if (count == 0) {
fprintf(pvtData.console,
FILE *console = pvtData.console ? pvtData.console : stderr;
fprintf(console,
"errlogRemoveListeners: No listeners found\n");
}
return count;
@@ -376,7 +385,7 @@ epicsShareFunc int epicsShareAPI eltc(int yesno)
epicsShareFunc int errlogSetConsole(FILE *stream)
{
errlogInit(0);
pvtData.console = stream ? stream : stderr;
pvtData.console = stream;
return 0;
}
@@ -405,17 +414,19 @@ epicsShareFunc void errPrintf(long status, const char *pFileName,
}
if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) {
FILE *console = pvtData.console ? pvtData.console : stderr;
if (pFileName)
fprintf(pvtData.console, "filename=\"%s\" line number=%d\n",
fprintf(console, "filename=\"%s\" line number=%d\n",
pFileName, lineno);
if (status > 0)
fprintf(pvtData.console, "%s ", name);
fprintf(console, "%s ", name);
va_start(pvar, pformat);
vfprintf(pvtData.console, pformat, pvar);
vfprintf(console, pformat, pvar);
va_end(pvar);
fputc('\n', pvtData.console);
fflush(pvtData.console);
fputc('\n', console);
fflush(console);
}
if (pvtData.atExit)
@@ -473,7 +484,7 @@ static void errlogInitPvt(void *arg)
ellInit(&pvtData.listenerList);
ellInit(&pvtData.msgQueue);
pvtData.toConsole = TRUE;
pvtData.console = stderr;
pvtData.console = NULL;
pvtData.waitForWork = epicsEventMustCreate(epicsEventEmpty);
pvtData.listenerLock = epicsMutexMustCreate();
pvtData.msgQueueLock = epicsMutexMustCreate();
@@ -559,8 +570,10 @@ static void errlogThread(void)
while ((pmessage = msgbufGetSend(&noConsoleMessage))) {
epicsMutexMustLock(pvtData.listenerLock);
if (pvtData.toConsole && !noConsoleMessage) {
fprintf(pvtData.console,"%s",pmessage);
fflush(pvtData.console);
FILE *console = pvtData.console ? pvtData.console : stderr;
fprintf(console, "%s", pmessage);
fflush(console);
}
plistenerNode = (listenerNode *)ellFirst(&pvtData.listenerList);
@@ -680,7 +693,9 @@ static void msgbufFreeSend(void)
epicsMutexMustLock(pvtData.msgQueueLock);
pnextSend = (msgNode *)ellFirst(&pvtData.msgQueue);
if (!pnextSend) {
fprintf(pvtData.console, "errlog: msgbufFreeSend logic error\n");
FILE *console = pvtData.console ? pvtData.console : stderr;
fprintf(console, "errlog: msgbufFreeSend logic error\n");
epicsThreadSuspendSelf();
}
ellDelete(&pvtData.msgQueue, &pnextSend->node);

View File

@@ -148,6 +148,10 @@ epicsShareFunc void epicsShareAPI freeListCleanup(void *pvt)
epicsShareFunc size_t epicsShareAPI freeListItemsAvail(void *pvt)
{
FREELISTPVT *pfl = pvt;
return pfl->nBlocksAvailable;
size_t nBlocksAvailable;
epicsMutexMustLock(pfl->lock);
nBlocksAvailable = pfl->nBlocksAvailable;
epicsMutexUnlock(pfl->lock);
return nBlocksAvailable;
}

View File

@@ -70,12 +70,12 @@ epicsShareFunc int
/* These macros return 1 if successful, 0 on failure.
* This is analagous to the return value from sscanf()
*/
#define epicsScanLong(str, to, base) !epicsParseLong(str, to, base, NULL)
#define epicsScanULong(str, to, base) !epicsParseULong(str, to, base, NULL)
#define epicsScanLLong(str, to, base) !epicsParseLLong(str, to, base, NULL)
#define epicsScanULLong(str, to, base) !epicsParseULLong(str, to, base, NULL)
#define epicsScanFloat(str, to) !epicsParseFloat(str, to, NULL)
#define epicsScanDouble(str, to) !epicsParseDouble(str, to, NULL)
#define epicsScanLong(str, to, base) (!epicsParseLong(str, to, base, NULL))
#define epicsScanULong(str, to, base) (!epicsParseULong(str, to, base, NULL))
#define epicsScanLLong(str, to, base) (!epicsParseLLong(str, to, base, NULL))
#define epicsScanULLong(str, to, base) (!epicsParseULLong(str, to, base, NULL))
#define epicsScanFloat(str, to) (!epicsParseFloat(str, to, NULL))
#define epicsScanDouble(str, to) (!epicsParseDouble(str, to, NULL))
#ifdef __cplusplus
}

View File

@@ -211,7 +211,7 @@ int testDone(void) {
/* Our test harness, for RTEMS and vxWorks */
static void harnessExit(void *dummy) {
void testHarnessExit(void *dummy) {
epicsTimeStamp ended;
int Faulty;
@@ -248,7 +248,7 @@ static void harnessExit(void *dummy) {
void testHarness(void) {
epicsThreadOnce(&onceFlag, testOnce, NULL);
epicsAtExit(harnessExit, NULL);
epicsAtExit(testHarnessExit, NULL);
Harness = 1;
Programs = 0;
Tests = 0;

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