Merge lp:~epics-core/epics-base/add-rtems-4.12-api into lp:~epics-core/epics-base/3.16

Proposed by Andrew Johnson
Status: Rejected
Rejected by: Andrew Johnson
Proposed branch: lp:~epics-core/epics-base/add-rtems-4.12-api
Merge into: lp:~epics-core/epics-base/3.16
Diff against target: 4073 lines (+2253/-730) (has conflicts)
41 files modified
Makefile (+1/-0)
README (+21/-0)
configure/CONFIG_COMMON (+7/-6)
configure/os/CONFIG.Common.RTEMS (+14/-1)
configure/os/CONFIG.Common.RTEMS-beatnik (+6/-5)
configure/os/CONFIG.Common.RTEMS-mvme3100 (+5/-3)
configure/os/CONFIG_SITE.Common.RTEMS (+20/-2)
configure/os/CONFIG_SITE.Common.RTEMS-beatnik (+22/-0)
configure/os/CONFIG_SITE.Common.RTEMS-mvme3100 (+19/-0)
configure/os/CONFIG_SITE.Common.RTEMS-pc386 (+12/-0)
documentation/RELEASE_NOTES.html (+29/-0)
src/ioc/rsrv/caservertask.c (+5/-1)
src/libCom/RTEMS/Makefile (+2/-0)
src/libCom/RTEMS/kernel/rtems_config.c (+6/-6)
src/libCom/RTEMS/kernel/rtems_netconfig.c (+56/-43)
src/libCom/RTEMS/posix/rtems_config.c (+88/-0)
src/libCom/RTEMS/posix/rtems_netconfig.c (+126/-0)
src/libCom/RTEMS/rtems_init.c (+145/-26)
src/libCom/calc/postfix.c (+14/-0)
src/libCom/error/errlog.c (+5/-0)
src/libCom/misc/epicsUnitTest.c (+1/-0)
src/libCom/osi/os/Linux/osdSock.h (+2/-0)
src/libCom/osi/os/RTEMS-posix/devLibVMEOSD.c (+367/-0)
src/libCom/osi/os/RTEMS-posix/osdInterrupt.c (+59/-0)
src/libCom/osi/os/RTEMS-posix/osdMessageQueue.cpp (+163/-0)
src/libCom/osi/os/RTEMS-posix/osdMessageQueue.h (+31/-0)
src/libCom/osi/os/RTEMS-posix/osdMutex.c (+6/-0)
src/libCom/osi/os/RTEMS-posix/osdPoolStatus.c (+34/-0)
src/libCom/osi/os/RTEMS-posix/osdSock.h (+111/-0)
src/libCom/osi/os/WIN32/osdNetIntf.c (+100/-202)
src/libCom/osi/os/default/osdNetIntf.c (+155/-320)
src/libCom/osi/os/posix/osdSockAddrReuse.cpp (+8/-1)
src/libCom/osi/os/posix/osdThread.c (+182/-109)
src/libCom/osi/os/posix/osdThreadExtra.c (+7/-3)
src/libCom/osi/osiSock.c (+157/-0)
src/libCom/osi/osiSock.h (+37/-0)
src/libCom/test/Makefile (+7/-0)
src/libCom/test/epicsMessageQueueTest.cpp (+1/-1)
src/libCom/test/epicsNetIntfTest.c (+220/-0)
src/libCom/test/epicsRunLibComTests.c (+2/-0)
src/libCom/test/ringPointerTest.c (+0/-1)
Text conflict in src/libCom/RTEMS/rtems_init.c
To merge this branch: bzr merge lp:~epics-core/epics-base/add-rtems-4.12-api
Reviewer Review Type Date Requested Status
Andrew Johnson Needs Fixing
Review via email: mp+320503@code.launchpad.net

Description of the change

Heinz's RTEMS-4.12 port with the additional OS_API flag and reorganized to allow switching between kernel and posix implementations. For RTEMS the flag's value is set automatically based on a new RTEMS_SERIES setting in CONFIG_SITE.Common.RTEMS.

I can't implement Michael's request to use explicit paths to the source files without making significant changes to the build rules, and that would probably break a large number of external modules; the OS_API approach is backwards compatible.

I have checked that this branch builds against both RTEMS-4.9.2 and 4.10.2, but I don't have RTEMS-4.12 here to try it against. I have reservations about some of the posix implementations which I will bring up in review comments.

To post a comment you must log in.
Revision history for this message
Andrew Johnson (anj) wrote :

Various inline comments and questions.

Revision history for this message
Andrew Johnson (anj) wrote :

A couple more inline comments/questions.

12746. By Heinz Junkes

in 'configure/os/CONFIG.Common.RTEMS-beatnik
set MY_DO_BOOTP to rtems_bsdnet_do_bootp as I have checked just
   "network booting" with dhcp. Booting with NVRAM-settings not tested until now

in src/libCom/RTEMS/posix/rtems_netconfig.c
Interface named defined in ./configure/os/CONFIG.Common.RTEMS-beatnik
ARCH_DEP_CFLAGS += -DETH_NAME_1=mve1
ARCH_DEP_CFAGS += -DETH_NAME_2=mve2
done just for powerpc-beatnik

Initial date in src/libCom/RTEMS/rtems_init.c
100 years after the sinking of the Titanik, I was 50 years old ;-)

src/libCom/osi/os/RTEMS-posix/devLibVMEOSD.c
I still do not know where where routine bspExtMemProb and bspExtInit() come from.

src/libCom/osi/os/posix/osdThread.c
No special rtems-version. I modified the "standard" posix osdThread.c
Add __thread (thread local variable) instead of posix key.
Other stack-space, printk statements, all with #if defined (__rtems__).
Hope this is ok.

12747. By Andrew Johnson

Network config changes, to generalize

12748. By mdavidsaver

libCom: rtems < 4.12 doesn't have SO_REUSEPORT

12749. By mdavidsaver

libCom/RTEMS: avoid multiple defs w/ RTEMS < 4.12

Revision history for this message
Andrew Johnson (anj) wrote :

This branch is *not* ready to merge, sorry, it needs some major cleaning up in places.

Please remove the extraneous comments from the README file.

There are some changes related to multicast options which will probably conflict with my osiSockTest branch (which is aimed at 3.15 but should be merged up first). The osiSockTest branch changes should take precedence over those from this branch.

Please remove the call to epicsThreadShowAll() from testHarness() in epicsUnitTest.c. There appear to be a few other extraneous changes (e.g. adding or removing blank lines to files which are otherwise unchanged) which I would like to see deleted. Code that should be indented but isn't, extraneous commented out lines etc. — these kinds of changes should never have been committed in the first place.

The various rtems-specific includes that have been added to a number of files (e.g. errlog.c) really should be put in an RTEMS-specific osd* header file, although I'm not sure which. We have tried to remove all OS-conditional includes from the general EPICS sources, and I don't want to let them back in again here.

I frown on the use of C++ // comments in .c files. Maybe they don't matter any more with the latest compilers, but I still have to support systems with compilers that don't allow them.

Does this branch include (some of) Michael's osiaddrinfo branch? There are changes in it which seem to be related to that and have his name on them, but I don't know the specifics. That branch had problems on MacOS and some other architectures, so this makes me a little nervous.

review: Needs Fixing
Revision history for this message
Heinz Junkes (junkes) wrote :

Dear Andrew,
thank you for your review.
For me it looks not like a diff to the merge request (and push) I made at ITER on 5th of october.

I pushed my code to git+ssh://<email address hidden>/~epics-core/epics-base/+git/add-rtems-4.12-api

git log shows :

commit 6633ba5483732cd715420f874a85aed11e7df5fb
Author: Heinz Junkes <email address hidden>
Date: Thu Oct 5 14:45:19 2017 +0200

    add define rtems for SO_REUSEPORT etc

commit 2c707a1deebb1072fe77068c0a5fa389aa266c04
Author: Heinz Junkes <email address hidden>
Date: Thu Oct 5 09:24:55 2017 +0200

    RTEMS4.12

commit fdfd324fa760521e106de6165042ceffc5bad4a1
Author: Michael Davidsaver <email address hidden>
Date: Sun Jun 18 20:53:28 2017 +0200

    travis-ci: run RTEMS tests

Cheers,
Heinz

> On 19 Oct 2017, at 04:17, Andrew Johnson <email address hidden> wrote:
>
> Review: Needs Fixing
>
> This branch is *not* ready to merge, sorry, it needs some major cleaning up in places.
>
> Please remove the extraneous comments from the README file.
>
> There are some changes related to multicast options which will probably conflict with my osiSockTest branch (which is aimed at 3.15 but should be merged up first). The osiSockTest branch changes should take precedence over those from this branch.
>
> Please remove the call to epicsThreadShowAll() from testHarness() in epicsUnitTest.c. There appear to be a few other extraneous changes (e.g. adding or removing blank lines to files which are otherwise unchanged) which I would like to see deleted. Code that should be indented but isn't, extraneous commented out lines etc. — these kinds of changes should never have been committed in the first place.
>
> The various rtems-specific includes that have been added to a number of files (e.g. errlog.c) really should be put in an RTEMS-specific osd* header file, although I'm not sure which. We have tried to remove all OS-conditional includes from the general EPICS sources, and I don't want to let them back in again here.
>
> I frown on the use of C++ // comments in .c files. Maybe they don't matter any more with the latest compilers, but I still have to support systems with compilers that don't allow them.
>
> Does this branch include (some of) Michael's osiaddrinfo branch? There are changes in it which seem to be related to that and have his name on them, but I don't know the specifics. That branch had problems on MacOS and some other architectures, so this makes me a little nervous.
>
> --
> https://code.launchpad.net/~epics-core/epics-base/add-rtems-4.12-api/+merge/320503
> Your team EPICS Core Developers is subscribed to branch lp:~epics-core/epics-base/3.16.

Revision history for this message
Andrew Johnson (anj) wrote :

Hello Heinz,

Ahhh, this merge request is for the old Bazaar branch, my sincere apologies for not noticing that. I will mark this one as old and propose a merge of your new version.

- Andrew

Unmerged revisions

12749. By mdavidsaver

libCom/RTEMS: avoid multiple defs w/ RTEMS < 4.12

12748. By mdavidsaver

libCom: rtems < 4.12 doesn't have SO_REUSEPORT

12747. By Andrew Johnson

Network config changes, to generalize

12746. By Heinz Junkes

in 'configure/os/CONFIG.Common.RTEMS-beatnik
set MY_DO_BOOTP to rtems_bsdnet_do_bootp as I have checked just
   "network booting" with dhcp. Booting with NVRAM-settings not tested until now

in src/libCom/RTEMS/posix/rtems_netconfig.c
Interface named defined in ./configure/os/CONFIG.Common.RTEMS-beatnik
ARCH_DEP_CFLAGS += -DETH_NAME_1=mve1
ARCH_DEP_CFAGS += -DETH_NAME_2=mve2
done just for powerpc-beatnik

Initial date in src/libCom/RTEMS/rtems_init.c
100 years after the sinking of the Titanik, I was 50 years old ;-)

src/libCom/osi/os/RTEMS-posix/devLibVMEOSD.c
I still do not know where where routine bspExtMemProb and bspExtInit() come from.

src/libCom/osi/os/posix/osdThread.c
No special rtems-version. I modified the "standard" posix osdThread.c
Add __thread (thread local variable) instead of posix key.
Other stack-space, printk statements, all with #if defined (__rtems__).
Hope this is ok.

12745. By Andrew Johnson

Convert to OS_API layout

12744. By Andrew Johnson

Support for OS_API variable

12743. By Heinz Junkes <email address hidden>

RTEMS4.12 Port for EPICS 3.16

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile'
2--- Makefile 2016-05-22 12:38:18 +0000
3+++ Makefile 2017-05-01 18:36:52 +0000
4@@ -8,6 +8,7 @@
5 #*************************************************************************
6
7 TOP = .
8+
9 include $(TOP)/configure/CONFIG
10
11 # Bootstrap resolution: tools not installed yet
12
13=== modified file 'README'
14--- README 2017-02-01 17:57:04 +0000
15+++ README 2017-05-01 18:36:52 +0000
16@@ -22,3 +22,24 @@
17 websites etc. is available on the EPICS home page at
18 http://www.aps.anl.gov/epics/
19
20+hpj:
21+In configure/CONFIG_COMMON add RTEMS_XVERSION
22+$(addprefix $(dir)/, os/$(OS_CLASS)$(RTEMS_XVERSION) $(POSIX_$(POSIX)) os/default ))
23+
24+add to $Home/configure/CONFIG_USER
25+
26+#FHI
27+EPICS_SITE_VERSION = fhi
28+#
29+RTEMS_VERSION = 4.12
30+#to use new libcom osd files
31+RTEMS_XVERSION = 4.12
32+
33+RTEMS_BASE = /home/h1/RTEMS/rtems-$(RTEMS_VERSION)
34+
35+# Runs on beatnik board (MVME6100)
36+CROSS_COMPILER_TARGET_ARCHS = RTEMS-beatnik
37+
38+ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=rtems_bsdnet_do_bootp
39+ARCH_DEP_CFLAGS += -DBSP_NVRAM_BASE_ADDR=0xf1110000
40+
41
42=== modified file 'configure/CONFIG_COMMON'
43--- configure/CONFIG_COMMON 2017-02-01 17:57:04 +0000
44+++ configure/CONFIG_COMMON 2017-05-01 18:36:52 +0000
45@@ -4,7 +4,7 @@
46 # Copyright (c) 2002 The Regents of the University of California, as
47 # Operator of Los Alamos National Laboratory.
48 # EPICS BASE is distributed subject to a Software License Agreement found
49-# in file LICENSE that is included with this distribution.
50+# in file LICENSE that is included with this distribution.
51 #*************************************************************************
52 #
53 # CONFIG_COMMON
54@@ -136,10 +136,11 @@
55 #--------------------------------------------------
56 # vpath directories
57 POSIX_YES = os/posix
58+OS_IMPL_DIRS = $(if $(OS_API),os/$(OS_CLASS)-$(OS_API),) os/$(OS_CLASS)
59 GENERIC_SRC_DIRS = .. $(SRC_DIRS)
60-OS_SRC_DIRS += . $(foreach dir, .. $(SRC_DIRS), \
61- $(addprefix $(dir)/, os/$(OS_CLASS) $(POSIX_$(POSIX)) os/default ))
62-CMPLR_SRC_DIRS += . $(foreach dir, .. $(SRC_DIRS), \
63+OS_SRC_DIRS += . $(foreach dir, $(GENERIC_SRC_DIRS), \
64+ $(addprefix $(dir)/, $(OS_IMPL_DIRS) $(POSIX_$(POSIX)) os/default ))
65+CMPLR_SRC_DIRS += . $(foreach dir, $(GENERIC_SRC_DIRS), \
66 $(addprefix $(dir)/, compiler/$(CMPLR_CLASS) compiler/default ))
67 ALL_SRC_DIRS = $(CMPLR_SRC_DIRS) $(OS_SRC_DIRS) $(GENERIC_SRC_DIRS)
68
69@@ -261,7 +262,7 @@
70 LIBRARY_SRC_CFLAGS=$($(patsubst $*,SHRLIB,$(findstring $*,$(LIBRARY_SRCS)))_CFLAGS)
71
72 #--------------------------------------------------
73-# prefix, suffix, and ldflags for loadable shared libraries
74+# prefix, suffix, and ldflags for loadable shared libraries
75 TARGET_LIB_LDFLAGS=$($(patsubst $*,LOADABLE_,$(findstring $*,$(LOADABLE_LIBRARY)))SHRLIB_LDFLAGS)
76 LOADABLE_SHRLIB_PREFIX=$(SHRLIB_PREFIX)
77 LOADABLE_SHRLIB_SUFFIX=$(SHRLIB_SUFFIX)
78@@ -459,5 +460,5 @@
79 SOURCE_INC = $(wildcard $(file) $(SOURCE_INC_bbb) )
80 SOURCE_INC_bbb = $(foreach dir, $(ALL_SRC_DIRS), $(SOURCE_INC_aaa) )
81 SOURCE_INC_aaa = $(addsuffix /$(file), $(dir) )
82-
83+
84 endif
85
86=== modified file 'configure/os/CONFIG.Common.RTEMS'
87--- configure/os/CONFIG.Common.RTEMS 2016-05-22 12:38:18 +0000
88+++ configure/os/CONFIG.Common.RTEMS 2017-05-01 18:36:52 +0000
89@@ -91,14 +91,27 @@
90 OS_CLASS = RTEMS
91
92 #--------------------------------------------------
93+# operating system API (src/os/<os_class>-<os_api>)
94+OS_API_4.7 = kernel
95+OS_API_4.8 = kernel
96+OS_API_4.9 = kernel
97+OS_API_4.10 = kernel
98+OS_API_4.11 = $(error RTEMS-4.11 is not currently supported)
99+# Later RTEMS versions will use posix, no need to specify
100+OS_API = $(firstword $(OS_API_$(RTEMS_SERIES)) posix)
101+
102+#--------------------------------------------------
103 # Operating system flags
104 OP_SYS_LDLIBS += -lrtemsCom -lc -lrtemscpu -lCom -lnfs -lm
105-OP_SYS_LDFLAGS += $(CPU_CFLAGS) -u Init \
106+
107+OP_SYS_LDFLAGS_posix += -u POSIX_Init
108+OP_SYS_LDFLAGS_kernel += -u Init \
109 $(PROJECT_RELEASE)/lib/no-dpmem.rel \
110 $(PROJECT_RELEASE)/lib/no-mp.rel \
111 $(PROJECT_RELEASE)/lib/no-part.rel \
112 $(PROJECT_RELEASE)/lib/no-signal.rel \
113 $(PROJECT_RELEASE)/lib/no-rtmon.rel
114+OP_SYS_LDFLAGS += $(CPU_CFLAGS) $(OP_SYS_LDFLAGS_$(OS_API))
115
116 MOD_SYS_LDFLAGS += $(CPU_CFLAGS) -Wl,-r -nostdlib
117
118
119=== modified file 'configure/os/CONFIG.Common.RTEMS-beatnik'
120--- configure/os/CONFIG.Common.RTEMS-beatnik 2016-05-21 02:27:03 +0000
121+++ configure/os/CONFIG.Common.RTEMS-beatnik 2017-05-01 18:36:52 +0000
122@@ -1,19 +1,20 @@
123-#
124 # CONFIG.Common.RTEMS-beatnik
125+#
126 # Author: Dayle Kotturi <dayle@slac.stanford.edu>
127 #
128-# All RTEMS targets use the same Makefile fragment
129+# Site-specific adjustments to these settings belong
130+# in the file CONFIG_SITE.Common.RTEMS-beatnik
131 #
132+
133 EXE = .elf
134 RTEMS_TARGET_CPU = powerpc
135 GNU_TARGET = powerpc-rtems
136-ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL
137+
138+# Flags for *all* beatnik builds
139 ARCH_DEP_CFLAGS += -DHAVE_MOTLOAD
140 ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_MBUF_SPACE=2048
141 ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_CLUSTER_SPACE=5120
142
143-OP_SYS_LDLIBS += -lbspExt
144-
145 MUNCH_SUFFIX = .boot
146 MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
147 define MUNCH_CMD
148
149=== modified file 'configure/os/CONFIG.Common.RTEMS-mvme3100'
150--- configure/os/CONFIG.Common.RTEMS-mvme3100 2016-05-21 02:27:03 +0000
151+++ configure/os/CONFIG.Common.RTEMS-mvme3100 2017-05-01 18:36:52 +0000
152@@ -1,18 +1,20 @@
153-#
154 # CONFIG.Common.RTEMS-mvme3100
155+#
156 # Author: W. Eric Norum <wenorum@lbl.gov>
157 #
158-# All RTEMS targets use the same Makefile fragment
159+# Site-specific adjustments to these settings belong
160+# in the file CONFIG_SITE.Common.RTEMS-mvme3100
161 #
162 EXE = .elf
163 RTEMS_TARGET_CPU = powerpc
164 GNU_TARGET = powerpc-rtems
165+
166 ARCH_DEP_CFLAGS += -DMY_DO_BOOTP=NULL
167 ARCH_DEP_CFLAGS += -DHAVE_MOTLOAD
168 ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_MBUF_SPACE=2048
169 ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_CONFIG_CLUSTER_SPACE=5120
170
171-OP_SYS_LDLIBS += -lbspExt
172+# OP_SYS_LDLIBS += -lbspExt
173
174 MUNCH_SUFFIX = .boot
175 MUNCHNAME = $(PRODNAME:%$(EXE)=%$(MUNCH_SUFFIX))
176
177=== modified file 'configure/os/CONFIG_SITE.Common.RTEMS'
178--- configure/os/CONFIG_SITE.Common.RTEMS 2016-05-21 02:27:03 +0000
179+++ configure/os/CONFIG_SITE.Common.RTEMS 2017-05-01 18:36:52 +0000
180@@ -3,11 +3,29 @@
181 # Site-specific information for all RTEMS targets
182 #-------------------------------------------------------
183
184+# RTEMS Series and Version
185+
186+#RTEMS_SERIES = 4.9
187+#RTEMS_VERSION = 4.9.2
188+
189+RTEMS_SERIES = 4.10
190+RTEMS_VERSION = 4.10.2
191+
192+#RTEMS_SERIES = 4.12
193+#RTEMS_VERSION = 4.12
194+
195+
196 # Where to find RTEMS
197 #
198+#RTEMS_BASE = /your/path/to/rtems-$(RTEMS_VERSION)
199+
200 # APS:
201-RTEMS_VERSION = 4.10.2
202 RTEMS_BASE = /usr/local/vw/rtems/rtems-$(RTEMS_VERSION)
203+#RTEMS_BASE = /local/anj/RTEMS/rtems-4.12
204+
205+# FHI:
206+#RTEMS_BASE = /home/rtems/RTEMS/rtems-$(RTEMS_VERSION)
207+
208
209 # Cross-compile toolchain in $(RTEMS_TOOLS)/bin
210 #
211@@ -24,7 +42,7 @@
212 # network configuration you must uncomment and specify your Internet
213 # Domain Name here
214 #
215-#OP_SYS_CFLAGS += -DRTEMS_NETWORK_CONFIG_DNS_DOMAINNAME=<domainname>
216+OP_SYS_CFLAGS += -DRTEMS_NETWORK_CONFIG_DNS_DOMAINNAME=<domainname>
217
218 # Select the command-line-input library to use
219 #
220
221=== added file 'configure/os/CONFIG_SITE.Common.RTEMS-beatnik'
222--- configure/os/CONFIG_SITE.Common.RTEMS-beatnik 1970-01-01 00:00:00 +0000
223+++ configure/os/CONFIG_SITE.Common.RTEMS-beatnik 2017-05-01 18:36:52 +0000
224@@ -0,0 +1,22 @@
225+# CONFIG_SITE.Common.RTEMS-beatnik
226+#
227+# Site-specific overrides for RTEMS-beatnik target
228+#
229+
230+# Any sites using the beatnik BSP on more than one kind of MVME
231+# board may have difficulties with this release...
232+
233+# These settings are for MVME6100 boards:
234+ARCH_DEP_CFLAGS += -DUSE_ALTIVEC
235+
236+ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_DRIVER_NAME_1=mve1
237+#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_IP4_ADDR_1=192.168.4.1
238+#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_IP4_MASK_1=255.255.254.0
239+
240+ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_DRIVER_NAME_2=mve2
241+#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_IP4_ADDR_2=192.168.6.2
242+#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_IP4_MASK_2=255.255.254.0
243+
244+# Uncomment this to link against libbspExt
245+#OP_SYS_LDLIBS += -lbspExt
246+
247
248=== added file 'configure/os/CONFIG_SITE.Common.RTEMS-mvme3100'
249--- configure/os/CONFIG_SITE.Common.RTEMS-mvme3100 1970-01-01 00:00:00 +0000
250+++ configure/os/CONFIG_SITE.Common.RTEMS-mvme3100 2017-05-01 18:36:52 +0000
251@@ -0,0 +1,19 @@
252+# CONFIG_SITE.Common.RTEMS-mvme3100
253+#
254+# Site-specific overrides for RTEMS-mvme3100 target
255+#
256+
257+# Any sites using the beatnik BSP on more than one kind of MVME
258+# board may have difficulties with this release...
259+
260+#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_DRIVER_NAME_1=?
261+#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_IP4_ADDR_1=192.168.4.1
262+#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_IP4_MASK_1=255.255.254.0
263+
264+#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_DRIVER_NAME_2=?
265+#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_IP4_ADDR_2=192.168.6.2
266+#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_IP4_MASK_2=255.255.254.0
267+
268+# Uncomment this to link against libbspExt
269+#OP_SYS_LDLIBS += -lbspExt
270+
271
272=== modified file 'configure/os/CONFIG_SITE.Common.RTEMS-pc386'
273--- configure/os/CONFIG_SITE.Common.RTEMS-pc386 2002-08-20 16:18:05 +0000
274+++ configure/os/CONFIG_SITE.Common.RTEMS-pc386 2017-05-01 18:36:52 +0000
275@@ -1,3 +1,15 @@
276+# CONFIG_SITE.Common.RTEMS-pc386
277 #
278 # Site-specific overrides for RTEMS-pc386 target
279 #
280+
281+# These NICs support run-time probing:
282+#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_DRIVER_NAME_1=fxp1
283+#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_DRIVER_ATTACH_1=rtems_fxp_attach
284+#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_IP4_ADDR_1=192.168.4.1
285+#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_IP4_MASK_1=255.255.254.0
286+
287+#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_DRIVER_NAME_2=ep0
288+#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_DRIVER_ATTACH_2=rtems_3c509_driver_attach
289+#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_IP4_ADDR_2=192.168.6.2
290+#ARCH_DEP_CFLAGS += -DRTEMS_NETWORK_IP4_MASK_2=255.255.254.0
291
292=== modified file 'documentation/RELEASE_NOTES.html'
293--- documentation/RELEASE_NOTES.html 2017-02-01 17:57:04 +0000
294+++ documentation/RELEASE_NOTES.html 2017-05-01 18:36:52 +0000
295@@ -21,6 +21,35 @@
296
297 -->
298
299+<h3>Support for RTEMS 4.12</h3>
300+
301+<p>The next major release of the RTEMS real-time OS will be version 4.12 which
302+contains many changes including the ability to support SMP systems. The earlier
303+EPICS support for RTEMS made use of various RTEMS-specific kernel APIs which
304+cannot be used on an SMP system, so the changes here required a completely new
305+port to the Posix real-time APIs that RTEMS-4.12 now recommends. A new RTEMS
306+configuration variable RTEMS_SERIES has been added which should be set to the
307+first two components of the OS version number, e.g. 4.9. When this is 4.12 or
308+greater the new libCom/osi/os/RTEMS-posix source files will be used; the older
309+API source files can now be found in libCom/osi/os/RTEMS-kernel, and those which
310+are common to both installations are in libCom/osi/os/RTEMS.</p>
311+
312+<p>Note that EPICS Base can only be built for a single RTEMS version at a time.
313+ The RTEMS version number is set in the CONFIG_SITE.Common.RTEMS file and
314+ cannot be different for specific targets. This allows different header files
315+ to be used and installed for the two different APIs.</p>
316+
317+<h3>Support for multiple APIs in the same OS</h3>
318+
319+<p>The build configuration files for a particular build target may now select
320+between multiple implementations with different OS APIs by setting the GNUmake
321+variable <tt>OS_API</tt>. This changes the search path used for OS-specific
322+source files, inserting a directory <tt>os/$(OS_CLASS)-$(OS_API)</tt> before
323+the existing <tt>os/$(OS_CLASS)</tt> directory. Note though that the include
324+file search path does not change, so OS-specific header files must be able to
325+handle both APIs simultaneously, and their source files should go in the
326+<tt>os/$(OS_CLASS)</tt> directory.</p>
327+
328 <h3>Echoless comments in iocsh</h3>
329
330 <p>The way comments are parsed by the iocsh interpreter has changed. The
331
332=== modified file 'src/ioc/rsrv/caservertask.c'
333--- src/ioc/rsrv/caservertask.c 2016-08-30 14:36:51 +0000
334+++ src/ioc/rsrv/caservertask.c 2017-05-01 18:36:52 +0000
335@@ -308,13 +308,17 @@
336 }
337 #ifdef IP_ADD_MEMBERSHIP
338 {
339+#if defined(__rtems__)
340+ char flag = 1;
341+#else
342 int flag = 1;
343+#endif
344 if (setsockopt(beaconSocket, IPPROTO_IP, IP_MULTICAST_LOOP,
345 (char *)&flag, sizeof(flag))<0) {
346 char sockErrBuf[64];
347 epicsSocketConvertErrnoToString (
348 sockErrBuf, sizeof ( sockErrBuf ) );
349- errlogPrintf("rsrv: failed to set mcast loopback\n");
350+ errlogPrintf("rsrv: failed to set mcast loopback (%d:%s)\n", errno, sockErrBuf);
351 }
352 }
353 #endif
354
355=== modified file 'src/libCom/RTEMS/Makefile'
356--- src/libCom/RTEMS/Makefile 2011-11-14 23:42:50 +0000
357+++ src/libCom/RTEMS/Makefile 2017-05-01 18:36:52 +0000
358@@ -9,6 +9,8 @@
359 TOP=../../..
360 include $(TOP)/configure/CONFIG
361
362+SRC_DIRS += ../$(OS_API)
363+
364 INC += epicsRtemsInitHooks.h
365
366 rtemsCom_SRCS += rtems_init.c
367
368=== added directory 'src/libCom/RTEMS/kernel'
369=== renamed file 'src/libCom/RTEMS/rtems_config.c' => 'src/libCom/RTEMS/kernel/rtems_config.c'
370--- src/libCom/RTEMS/rtems_config.c 2016-05-22 12:38:18 +0000
371+++ src/libCom/RTEMS/kernel/rtems_config.c 2017-05-01 18:36:52 +0000
372@@ -1,17 +1,17 @@
373 /*************************************************************************\
374 * Copyright (c) 2002 The University of Saskatchewan
375-* EPICS BASE Versions 3.13.7
376-* and higher are distributed subject to a Software License Agreement found
377-* in file LICENSE that is included with this distribution.
378+* EPICS BASE is distributed subject to a Software License Agreement found
379+* in file LICENSE that is included with this distribution.
380 \*************************************************************************/
381 /*
382 * RTEMS configuration for EPICS
383 * Author: W. Eric Norum
384- * norume@aps.anl.gov
385- * (630) 252-4793
386 */
387
388 #include <rtems.h>
389+#include <epicsVersion.h>
390+#define RTEMS_VERSION_INT \
391+ VERSION_INT(__RTEMS_MAJOR__, __RTEMS_MINOR__, __RTEMS_REVISION__, 0)
392
393 /*
394 ***********************************************************************
395@@ -20,7 +20,7 @@
396 */
397 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
398
399-#if __RTEMS_MAJOR__>4 || (__RTEMS_MAJOR__==4 && __RTEMS_MINOR__>9) || (__RTEMS_MAJOR__==4 && __RTEMS_MINOR__==9 && __RTEMS_REVISION__==99)
400+#if RTEMS_VERSION_INT >= VERSION_INT(4, 9, 99, 0)
401 # define CONFIGURE_UNIFIED_WORK_AREAS
402 #else
403 # define CONFIGURE_EXECUTIVE_RAM_SIZE (2000*1024)
404
405=== renamed file 'src/libCom/RTEMS/rtems_netconfig.c' => 'src/libCom/RTEMS/kernel/rtems_netconfig.c'
406--- src/libCom/RTEMS/rtems_netconfig.c 2016-05-22 12:38:18 +0000
407+++ src/libCom/RTEMS/kernel/rtems_netconfig.c 2017-05-01 18:36:52 +0000
408@@ -19,55 +19,70 @@
409 extern void rtems_bsdnet_loopattach();
410 static struct rtems_bsdnet_ifconfig loopback_config = {
411 "lo0", /* name */
412- (int (*)(struct rtems_bsdnet_ifconfig *, int))rtems_bsdnet_loopattach, /* attach function */
413- NULL, /* link to next interface */
414+ (int (*)(struct rtems_bsdnet_ifconfig *, int))rtems_bsdnet_loopattach,
415+ NULL, /* last interface */
416 "127.0.0.1", /* IP address */
417 "255.0.0.0", /* IP net mask */
418 };
419
420+#define stringOf(x) #x
421+#define STRING(x) stringOf(x)
422+
423 /*
424- * The following conditionals select the network interface card.
425- *
426- * On RTEMS-pc386 targets all network drivers which support run-time
427- * probing are linked.
428- * On other targets the network interface specified by the board-support
429- * package is used.
430- * To use a different NIC for a particular application, copy this file to the
431- * application directory and make the appropriate changes.
432+ * The following configures up to 2 network interface card(s) using
433+ * settings in either configure/os/CONFIG_SITE.Common.RTEMS or in a
434+ * BSP-specific configure/os/CONFIG_SITE.Common.RTEMS-<bsp> file.
435+ * If no settings are provided, it uses the BSP's defaults instead.
436 */
437-#if defined(__i386__)
438-extern int rtems_fxp_attach (struct rtems_bsdnet_ifconfig *, int);
439-static struct rtems_bsdnet_ifconfig fxp_driver_config = {
440- "fxp1", /* name */
441- rtems_fxp_attach, /* attach function */
442- &loopback_config, /* link to next interface */
443-};
444-extern int rtems_3c509_driver_attach (struct rtems_bsdnet_ifconfig *, int);
445-static struct rtems_bsdnet_ifconfig e3c509_driver_config = {
446- "ep0", /* name */
447- rtems_3c509_driver_attach, /* attach function */
448- &fxp_driver_config, /* link to next interface */
449-};
450-#define FIRST_DRIVER_CONFIG &e3c509_driver_config
451-#else
452-
453-# if defined(__PPC)
454- /*
455- * FIXME: This really belongs in the BSP
456- */
457-# ifndef RTEMS_BSP_NETWORK_DRIVER_NAME
458-# define RTEMS_BSP_NETWORK_DRIVER_NAME "dc1"
459-# endif
460-# ifndef RTEMS_BSP_NETWORK_DRIVER_ATTACH
461-# define RTEMS_BSP_NETWORK_DRIVER_ATTACH rtems_dec21140_driver_attach
462- extern int rtems_dec21140_driver_attach();
463-# endif
464-# endif
465-
466+
467+#if defined(RTEMS_NETWORK_DRIVER_NAME_1)
468+
469+ #if defined(RTEMS_NETWORK_DRIVER_NAME_2)
470+ static struct rtems_bsdnet_ifconfig netdriver_config_2 = {
471+ STRING(RTEMS_NETWORK_DRIVER_NAME_2),
472+ #if defined(RTEMS_NETWORK_DRIVER_ATTACH_2)
473+ RTEMS_NETWORK_DRIVER_ATTACH_2, /* specific attach function */
474+ #else
475+ RTEMS_BSP_NETWORK_DRIVER_ATTACH, /* default attach function */
476+ #endif
477+ &loopback_config, /* loopback interface */
478+ #if defined(RTEMS_NETWORK_IP4_ADDR_2)
479+ STRING(RTEMS_NETWORK_IP4_ADDR_2),
480+ #if defined(RTEMS_NETWORK_IP4_MASK_2)
481+ STRING(RTEMS_NETWORK_IP4_MASK_2),
482+ #endif
483+ #endif
484+ };
485+ #endif /* RTEMS_NETWORK_DRIVER_NAME_2 */
486+
487+ static struct rtems_bsdnet_ifconfig netdriver_config = {
488+ STRING(RTEMS_NETWORK_DRIVER_NAME_1),
489+ #if defined(RTEMS_NETWORK_DRIVER_ATTACH_1)
490+ RTEMS_NETWORK_DRIVER_ATTACH_1, /* specific attach function */
491+ #else
492+ RTEMS_BSP_NETWORK_DRIVER_ATTACH, /* default attach function */
493+ #endif
494+ #if defined(RTEMS_NETWORK_DRIVER_NAME_2)
495+ &netdriver_config_2, /* link to next interface */
496+ #else
497+ &loopback_config, /* loopback interface */
498+ #endif
499+ #if defined(RTEMS_NETWORK_IP4_ADDR_1)
500+ STRING(RTEMS_NETWORK_IP4_ADDR_1),
501+ #if defined(RTEMS_NETWORK_IP4_MASK_1)
502+ STRING(RTEMS_NETWORK_IP4_MASK_1),
503+ #endif
504+ #endif
505+ };
506+ #define FIRST_DRIVER_CONFIG &netdriver_config
507+
508+#else /* RTEMS_NETWORK_DRIVER_NAME_1 */
509+
510+/* Use the BSP-provided standard macros */
511 static struct rtems_bsdnet_ifconfig bsp_driver_config = {
512 RTEMS_BSP_NETWORK_DRIVER_NAME, /* name */
513 RTEMS_BSP_NETWORK_DRIVER_ATTACH, /* attach function */
514- &loopback_config, /* link to next interface */
515+ &loopback_config, /* loopback interface */
516 };
517 #define FIRST_DRIVER_CONFIG &bsp_driver_config
518
519@@ -77,9 +92,7 @@
520 * Allow configure/os/CONFIG_SITE.Common.RTEMS to provide domain name
521 */
522 #ifdef RTEMS_NETWORK_CONFIG_DNS_DOMAINNAME
523-# define XSTR(x) STR(x)
524-# define STR(x) #x
525-# define MY_DOMAINNAME XSTR(RTEMS_NETWORK_CONFIG_DNS_DOMAINNAME)
526+# define MY_DOMAINNAME STRING(RTEMS_NETWORK_CONFIG_DNS_DOMAINNAME)
527 #else
528 # define MY_DOMAINNAME NULL
529 #endif
530
531=== added directory 'src/libCom/RTEMS/posix'
532=== added file 'src/libCom/RTEMS/posix/rtems_config.c'
533--- src/libCom/RTEMS/posix/rtems_config.c 1970-01-01 00:00:00 +0000
534+++ src/libCom/RTEMS/posix/rtems_config.c 2017-05-01 18:36:52 +0000
535@@ -0,0 +1,88 @@
536+/*************************************************************************\
537+* Copyright (c) 2002 The University of Saskatchewan
538+* Copyright (c) 2017 Fritz-Haber-Institut der Max-Planck-Gesellschafto* EPICS
539+* BASE is distributed subject to a Software License Agreement found
540+* * in file LICENSE that is included with this distribution.
541+\*************************************************************************/
542+/*
543+ * RTEMS configuration for EPICS
544+ * Author: W. Eric Norum
545+ * Heinz Junkes
546+ *
547+ * Version for RTEMS-4.12
548+ */
549+
550+#include <rtems.h>
551+
552+/*
553+ ***********************************************************************
554+ * RTEMS CONFIGURATION *
555+ ***********************************************************************
556+ */
557+
558+extern void *EPICS_WITH_POSIX_Init(void *argument);
559+
560+#define CONFIGURE_POSIX_INIT_THREAD_TABLE
561+#define CONFIGURE_POSIX_INIT_THREAD_ENTRY_POINT EPICS_WITH_POSIX_Init
562+/*
563+ * nfs is using rtems tasks
564+ */
565+#define CONFIGURE_MAXIMUM_TASKS 5
566+#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 5
567+#define CONFIGURE_MAXIMUM_SEMAPHORES 5
568+#define CONFIGURE_MAXIMUM_EVENTS 5
569+
570+#define CONFIGURE_MAXIMUM_POSIX_MUTEXES 300
571+#define CONFIGURE_MAXIMUM_POSIX_THREADS 200
572+#define CONFIGURE_MAXIMUM_POSIX_KEYS 200
573+#define CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS 200
574+#define CONFIGURE_MAXIMUM_POSIX_SPINLOCKS 100
575+#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES 300
576+#define CONFIGURE_MAXIMUM_POSIX_TIMERS 100
577+#define CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES 100
578+#define CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES 300
579+
580+#define CONFIGURE_UNIFIED_WORK_AREAS
581+
582+#define CONFIGURE_MAXIMUM_PERIODS 5
583+#define CONFIGURE_MICROSECONDS_PER_TICK 10000
584+#define CONFIGURE_MALLOC_STATISTICS 1
585+/* MINIMUM_STACK_SIZE == 8K */
586+#define CONFIGURE_EXTRA_TASK_STACKS (1000 * RTEMS_MINIMUM_STACK_SIZE)
587+
588+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
589+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
590+
591+#define CONFIGURE_FILESYSTEM_DEVFS
592+#define CONFIGURE_FILESYSTEM_TFTPFS
593+#define CONFIGURE_FILESYSTEM_NFS
594+#define CONFIGURE_FILESYSTEM_IMFS
595+#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
596+#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 150
597+
598+#define CONFIGURE_MAXIMUM_NFS_MOUNTS 3
599+#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 5
600+
601+#define CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE (64*1024)
602+
603+#define CONFIGURE_MAXIMUM_DRIVERS 8
604+
605+//#define CONFIGURE_INITIAL_EXTENSIONS { .fatal = fatal_extension }
606+
607+#define CONFIGURE_INIT
608+
609+
610+/*
611+ * This should be made BSP dependent, not CPU dependent but I know of no
612+ * appropriate conditionals to use.
613+ * The new general time support makes including the RTC driverr less important.
614+ */
615+#if !defined(mpc604) && !defined(__mc68040__) && !defined(__mcf5200__) && \
616+ !defined(mpc7455) && !defined(__arm__) && !defined(__nios2__)
617+ /* don't have RTC code */
618+#define CONFIGURE_APPLICATION_NEEDS_RTC_DRIVER
619+#endif
620+
621+
622+#include <bsp.h>
623+#include <rtems/confdefs.h>
624
625=== added file 'src/libCom/RTEMS/posix/rtems_netconfig.c'
626--- src/libCom/RTEMS/posix/rtems_netconfig.c 1970-01-01 00:00:00 +0000
627+++ src/libCom/RTEMS/posix/rtems_netconfig.c 2017-05-01 18:36:52 +0000
628@@ -0,0 +1,126 @@
629+/*************************************************************************\
630+* Copyright (c) 2002 The University of Saskatchewan
631+* Copyright (c) 2017 Fritz-Haber-Institut der Max-Planck-Gesellschaft
632+* EPICS BASE is distributed subject to a Software License Agreement found
633+* in file LICENSE that is included with this distribution.
634+\*************************************************************************/
635+/*
636+ * RTEMS network configuration for EPICS
637+ * Author: W. Eric Norum
638+ * Heinz Junkes
639+ *
640+ * Version for RTEMS-4.12
641+ *
642+ * This file can be copied to an application source dirctory
643+ * and modified to override the values shown below.
644+ */
645+#include <stdio.h>
646+#include <bsp.h>
647+#include <rtems/rtems_bsdnet.h>
648+
649+#define stringOf(x) #x
650+#define STRING(x) stringOf(x)
651+
652+/*
653+ * The following configures up to 2 network interface card(s) using
654+ * settings in either configure/os/CONFIG_SITE.Common.RTEMS or in a
655+ * BSP-specific configure/os/CONFIG_SITE.Common.RTEMS-<bsp> file.
656+ * If no settings are provided, it uses the BSP's defaults instead.
657+ */
658+
659+#if defined(RTEMS_NETWORK_DRIVER_NAME_1)
660+
661+ #if defined(RTEMS_NETWORK_DRIVER_NAME_2)
662+ static struct rtems_bsdnet_ifconfig netdriver_config_2 = {
663+ STRING(RTEMS_NETWORK_DRIVER_NAME_2),
664+ #if defined(RTEMS_NETWORK_DRIVER_ATTACH_2)
665+ RTEMS_NETWORK_DRIVER_ATTACH_2, /* specific attach function */
666+ #else
667+ RTEMS_BSP_NETWORK_DRIVER_ATTACH, /* default attach function */
668+ #endif
669+ NULL, /* last interface */
670+ #if defined(RTEMS_NETWORK_IP4_ADDR_2)
671+ STRING(RTEMS_NETWORK_IP4_ADDR_2),
672+ #if defined(RTEMS_NETWORK_IP4_MASK_2)
673+ STRING(RTEMS_NETWORK_IP4_MASK_2),
674+ #endif
675+ #endif
676+ };
677+ #endif /* RTEMS_NETWORK_DRIVER_NAME_2 */
678+
679+ static struct rtems_bsdnet_ifconfig netdriver_config = {
680+ STRING(RTEMS_NETWORK_DRIVER_NAME_1),
681+ #if defined(RTEMS_NETWORK_DRIVER_ATTACH_1)
682+ RTEMS_NETWORK_DRIVER_ATTACH_1, /* specific attach function */
683+ #else
684+ RTEMS_BSP_NETWORK_DRIVER_ATTACH, /* default attach function */
685+ #endif
686+ #if defined(RTEMS_NETWORK_DRIVER_NAME_2)
687+ &netdriver_config_2, /* link to next interface */
688+ #else
689+ NULL, /* last interface */
690+ #endif
691+ #if defined(RTEMS_NETWORK_IP4_ADDR_1)
692+ STRING(RTEMS_NETWORK_IP4_ADDR_1),
693+ #if defined(RTEMS_NETWORK_IP4_MASK_1)
694+ STRING(RTEMS_NETWORK_IP4_MASK_1),
695+ #endif
696+ #endif
697+ };
698+ #define FIRST_DRIVER_CONFIG &netdriver_config
699+
700+#else /* RTEMS_NETWORK_DRIVER_NAME_1 */
701+
702+/* Use the BSP-provided standard macros */
703+static struct rtems_bsdnet_ifconfig bsp_driver_config = {
704+ RTEMS_BSP_NETWORK_DRIVER_NAME, /* name */
705+ RTEMS_BSP_NETWORK_DRIVER_ATTACH, /* attach function */
706+ NULL, /* last interface */
707+};
708+#define FIRST_DRIVER_CONFIG &bsp_driver_config
709+
710+#endif
711+
712+/*
713+ * Allow configure/os/CONFIG_SITE.Common.RTEMS to provide domain name
714+ */
715+#ifdef RTEMS_NETWORK_CONFIG_DNS_DOMAINNAME
716+# define MY_DOMAINNAME STRING(RTEMS_NETWORK_CONFIG_DNS_DOMAINNAME)
717+#else
718+# define MY_DOMAINNAME NULL
719+#endif
720+
721+/*
722+ * Allow non-BOOTP network configuration
723+ */
724+#ifndef MY_DO_BOOTP
725+# define MY_DO_BOOTP rtems_bsdnet_do_bootp
726+#endif
727+
728+/*
729+ * Allow site- and BSP-specific network buffer space configuration.
730+ * The macro values are specified in KBytes.
731+ */
732+#ifndef RTEMS_NETWORK_CONFIG_MBUF_SPACE
733+# define RTEMS_NETWORK_CONFIG_MBUF_SPACE 180
734+#endif
735+#ifndef RTEMS_NETWORK_CONFIG_CLUSTER_SPACE
736+# define RTEMS_NETWORK_CONFIG_CLUSTER_SPACE 350
737+#endif
738+
739+/*
740+ * Network configuration
741+ */
742+struct rtems_bsdnet_config rtems_bsdnet_config = {
743+ FIRST_DRIVER_CONFIG, /* Link to next interface */
744+ MY_DO_BOOTP, /* How to find network config */
745+ 10, /* If 0 then the network daemons will run at a */
746+ /* priority just less than the lowest-priority */
747+ /* EPICS scan thread. */
748+ /* If non-zero then the network daemons will run */
749+ /* at this *RTEMS* priority */
750+ RTEMS_NETWORK_CONFIG_MBUF_SPACE*1024,
751+ RTEMS_NETWORK_CONFIG_CLUSTER_SPACE*1024,
752+ NULL, /* Host name */
753+ MY_DOMAINNAME, /* Domain name */
754+};
755
756=== modified file 'src/libCom/RTEMS/rtems_init.c'
757--- src/libCom/RTEMS/rtems_init.c 2017-02-01 17:57:04 +0000
758+++ src/libCom/RTEMS/rtems_init.c 2017-05-01 18:36:52 +0000
759@@ -25,12 +25,19 @@
760 #include <netinet/in.h>
761 #include <arpa/inet.h>
762 #include <rtems.h>
763+#include <epicsVersion.h>
764+#define RTEMS_VERSION_INT \
765+ VERSION_INT(__RTEMS_MAJOR__, __RTEMS_MINOR__, __RTEMS_REVISION__, 0)
766 #include <rtems/malloc.h>
767 #include <rtems/error.h>
768 #include <rtems/stackchk.h>
769 #include <rtems/rtems_bsdnet.h>
770 #include <rtems/imfs.h>
771 #include <librtemsNfs.h>
772+#if RTEMS_VERSION_INT >= VERSION_INT(4, 11, 99, 0)
773+#include <rtems/libio.h>
774+#include <sys/stat.h>
775+#endif
776 #include <bsp.h>
777
778 #include "epicsThread.h"
779@@ -44,6 +51,13 @@
780 #include "osdTime.h"
781
782 #include "epicsRtemsInitHooks.h"
783+#if RTEMS_VERSION_INT >= VERSION_INT(4, 11, 99, 0)
784+#include <rtems/malloc.h>
785+#include <rtems/score/heap.h>
786+#include <pthread.h>
787+#include <assert.h>
788+#define rtems_test_assert(_a) assert(_a)
789+#endif
790
791 /*
792 * Prototypes for some functions not in header files
793@@ -52,6 +66,49 @@
794 int fileno(FILE *);
795 int main(int argc, char **argv);
796
797+//Helper function must be made useful
798+#if RTEMS_VERSION_INT >= VERSION_INT(4, 11, 99, 0)
799+
800+static int get_current_prio( pthread_t thread )
801+{
802+rtems_status_code sc;
803+rtems_task_priority prio;
804+int max;
805+
806+sc = rtems_task_set_priority( thread, RTEMS_CURRENT_PRIORITY, &prio );
807+rtems_test_assert( sc == RTEMS_SUCCESSFUL );
808+
809+max = sched_get_priority_max( SCHED_FIFO );
810+
811+return max + 1 - (int) prio;
812+}
813+
814+//We are using posix map osi 0-100 to posix 100-200
815+int epicsThreadGetOsiPriorityValue(int ossPriority)
816+{
817+ if (ossPriority > 200) {
818+ return epicsThreadPriorityMax;
819+ }
820+ else if (ossPriority < 100) {
821+ return epicsThreadPriorityMin;
822+ }
823+ else {
824+ return ((unsigned int)ossPriority - 100u);
825+ }
826+}
827+int epicsThreadGetOssPriorityValue(unsigned int osiPriority)
828+{
829+ if (osiPriority > 99) {
830+ return 200;
831+ }
832+ else {
833+ return ((signed int)osiPriority + 100u);
834+ }
835+}
836+#else
837+/* see osdThread.c */
838+#endif
839+
840 static void
841 logReset (void)
842 {
843@@ -61,10 +118,12 @@
844 if (fp) {
845 char buf[80];
846 fp(buf, sizeof buf);
847- errlogPrintf ("Startup after %s.\n", buf);
848+ //errlogPrintf ("Startup after %s.\n", buf);
849+ printk ("Startup after %s.\n", buf);
850 }
851 else {
852- errlogPrintf ("Startup.\n");
853+ //errlogPrintf ("Startup.\n");
854+ printk ("Startup.\n");
855 }
856 }
857
858@@ -79,9 +138,12 @@
859 static void
860 delayedPanic (const char *msg)
861 {
862+#if RTEMS_VERSION_INT >= VERSION_INT(4, 11, 99, 0)
863+ rtems_task_wake_after (rtems_clock_get_ticks_per_second());
864+#else
865 extern rtems_interval rtemsTicksPerSecond;
866-
867 rtems_task_wake_after (rtemsTicksPerSecond);
868+#endif
869 rtems_panic (msg);
870 }
871
872@@ -171,9 +233,7 @@
873 }
874
875 #ifndef OMIT_NFS_SUPPORT
876-#if __RTEMS_MAJOR__>4 || \
877- (__RTEMS_MAJOR__==4 && __RTEMS_MINOR__>9) || \
878- (__RTEMS_MAJOR__==4 && __RTEMS_MINOR__==9 && __RTEMS_REVISION__==99)
879+#if RTEMS_VERSION_INT >= VERSION_INT(4, 9, 99, 0)
880 int
881 nfsMount(char *uidhost, char *path, char *mntpoint)
882 {
883@@ -187,6 +247,13 @@
884 }
885 sprintf(dev, "%s:%s", uidhost, path);
886 printf("Mount %s on %s\n", dev, mntpoint);
887+#if RTEMS_VERSION_INT >= VERSION_INT(4, 11, 99, 0)
888+ rval = mount_and_make_target_path (
889+ dev, mntpoint, RTEMS_FILESYSTEM_TYPE_NFS,
890+ RTEMS_FILESYSTEM_READ_WRITE, NULL );
891+ if(rval)
892+ perror("mount failed");
893+#else
894 if (rtems_mkdir(mntpoint, S_IRWXU | S_IRWXG | S_IRWXO))
895 printf("Warning -- unable to make directory \"%s\"\n", mntpoint);
896 if (mount(dev, mntpoint, RTEMS_FILESYSTEM_TYPE_NFS,
897@@ -196,6 +263,7 @@
898 else {
899 rval = 0;
900 }
901+#endif
902 free(dev);
903 return rval;
904 }
905@@ -210,9 +278,7 @@
906 {
907 #ifdef OMIT_NFS_SUPPORT
908 printf ("***** Initializing TFTP *****\n");
909-#if __RTEMS_MAJOR__>4 || \
910- (__RTEMS_MAJOR__==4 && __RTEMS_MINOR__>9) || \
911- (__RTEMS_MAJOR__==4 && __RTEMS_MINOR__==9 && __RTEMS_REVISION__==99)
912+#if RTEMS_VERSION_INT >= VERSION_INT(4, 9, 99, 0)
913 mount_and_make_target_path(NULL,
914 "/TFTP",
915 RTEMS_FILESYSTEM_TYPE_TFTPFS,
916@@ -246,6 +312,7 @@
917 printf ("***** Initializing NFS *****\n");
918 NFS_INIT
919 if (env_nfsServer && env_nfsPath && env_nfsMountPoint) {
920+ printf(" bin in environment kram ...\n");
921 server_name = env_nfsServer;
922 server_path = env_nfsPath;
923 mount_point = env_nfsMountPoint;
924@@ -309,10 +376,11 @@
925 "%[^:] : / %s",
926 pServerName,
927 pServerPath + 1u );
928+
929 if ( scanfStatus == 2 ) {
930 pServerPath[0u]= '/';
931 server_name = pServerName;
932- server_path = pServerPath;
933+ server_path = mount_point = pServerPath;
934 }
935 else {
936 free ( pServerName );
937@@ -332,8 +400,6 @@
938 argv[1] = abspath;
939 }
940 }
941- errlogPrintf("nfsMount(\"%s\", \"%s\", \"%s\")\n",
942- server_name, server_path, mount_point);
943 nfsMount(server_name, server_path, mount_point);
944 #endif
945 }
946@@ -357,7 +423,6 @@
947 perror("error: fixup_hosts stat /etc/hosts");
948 return;
949 }
950-
951 ret = mkdir("/etc", 0775);
952 if(ret!=0 && errno!=EEXIST)
953 {
954@@ -374,7 +439,6 @@
955 {
956 perror("error: failed to write /etc/hosts");
957 }
958-
959 fclose(fp);
960 }
961
962@@ -444,11 +508,19 @@
963 static const iocshFuncDef heapSpaceFuncDef = {"heapSpace",0,NULL};
964 static void heapSpaceCallFunc(const iocshArgBuf *args)
965 {
966+#if RTEMS_VERSION_INT >= VERSION_INT(4, 11, 99, 0)
967+ Heap_Information_block info;
968+ double x;
969+
970+ malloc_info (&info);
971+ x = info.Stats.size - (unsigned long)(info.Stats.lifetime_allocated - info.Stats.lifetime_freed);
972+#else
973 rtems_malloc_statistics_t s;
974 double x;
975
976 malloc_get_statistics(&s);
977 x = s.space_available - (unsigned long)(s.lifetime_allocated - s.lifetime_freed);
978+#endif
979 if (x >= 1024*1024)
980 printf("Heap space: %.1f MB\n", x / (1024 * 1024));
981 else
982@@ -513,13 +585,14 @@
983 * Ensure that the configuration object files
984 * get pulled in from the library
985 */
986-extern rtems_configuration_table Configuration;
987+#if RTEMS_VERSION_INT < VERSION_INT(4, 11, 99, 0)
988+extern rtems_configuration_table Configuration;
989 extern struct rtems_bsdnet_config rtems_bsdnet_config;
990 const void *rtemsConfigArray[] = {
991 &Configuration,
992 &rtems_bsdnet_config
993 };
994-
995+#endif
996 /*
997 * Hook to ensure that BSP cleanup code gets run on exit
998 */
999@@ -532,13 +605,21 @@
1000 /*
1001 * RTEMS Startup task
1002 */
1003+#if RTEMS_VERSION_INT >= VERSION_INT(4, 11, 99, 0)
1004+void *
1005+EPICS_WITH_POSIX_Init (void *argument)
1006+#else
1007 rtems_task
1008 Init (rtems_task_argument ignored)
1009+#endif
1010 {
1011+<<<<<<< TREE
1012 int result;
1013+=======
1014+ int i;
1015+>>>>>>> MERGE-SOURCE
1016 char *argv[3] = { NULL, NULL, NULL };
1017 char *cp;
1018- rtems_task_priority newpri;
1019 rtems_status_code sc;
1020 rtems_time_of_day now;
1021
1022@@ -562,10 +643,20 @@
1023 /*
1024 * Override RTEMS configuration
1025 */
1026- rtems_task_set_priority (
1027- RTEMS_SELF,
1028- epicsThreadGetOssPriorityValue(epicsThreadPriorityIocsh),
1029- &newpri);
1030+#if RTEMS_VERSION_INT >= VERSION_INT(4, 11, 99, 0)
1031+ int policy;
1032+ struct sched_param param;
1033+
1034+ if (pthread_getschedparam(pthread_self(), &policy, &param) != 0)
1035+ delayedPanic("pthread_getschedparam failed");
1036+ param.sched_priority = epicsThreadGetOssPriorityValue(epicsThreadPriorityIocsh);
1037+ if (pthread_setschedparam(pthread_self(), policy, &param) != 0)
1038+ delayedPanic("pthread_setschedparam failed");
1039+#else
1040+ rtems_task_priority newpri;
1041+ rtems_task_set_priority (RTEMS_SELF,
1042+ epicsThreadGetOssPriorityValue(epicsThreadPriorityIocsh), &newpri);
1043+#endif
1044
1045 /*
1046 * Create a reasonable environment
1047@@ -580,6 +671,7 @@
1048 printf("\n***** RTEMS Version: %s *****\n",
1049 rtems_get_version_string());
1050
1051+ printf("\n***** RTEMS min stack size : %d\n", RTEMS_MINIMUM_STACK_SIZE);
1052 /*
1053 * Start network
1054 */
1055@@ -616,12 +708,16 @@
1056 * It is very likely that other time synchronization facilities in EPICS
1057 * will soon override this value.
1058 */
1059+#if RTEMS_VERSION_INT >= VERSION_INT(4, 11, 99, 0)
1060+ if (rtems_clock_get_tod(&now) != RTEMS_SUCCESSFUL) {
1061+#else
1062 if (rtems_clock_get(RTEMS_CLOCK_GET_TOD,&now) != RTEMS_SUCCESSFUL) {
1063- now.year = 2001;
1064- now.month = 1;
1065- now.day = 1;
1066- now.hour = 0;
1067- now.minute = 0;
1068+#endif
1069+ now.year = 2012;
1070+ now.month = 4;
1071+ now.day = 14;
1072+ now.hour = 7;
1073+ now.minute = 23;
1074 now.second = 0;
1075 now.ticks = 0;
1076 if ((sc = rtems_clock_set (&now)) != RTEMS_SUCCESSFUL)
1077@@ -649,7 +745,23 @@
1078 }
1079 }
1080 tzset();
1081+#if RTEMS_VERSION_INT >= VERSION_INT(4, 11, 99, 0)
1082+ // osdTimeRegister() was called during C++ initialization
1083+#else
1084 osdTimeRegister();
1085+#endif
1086+
1087+ /*
1088+ * Some network diagnotics
1089+ */
1090+
1091+ // rtems_bsdnet_show_mbuf_stats (void);
1092+ rtems_bsdnet_show_if_stats ();
1093+ rtems_bsdnet_show_ip_stats ();
1094+ rtems_bsdnet_show_icmp_stats ();
1095+ rtems_bsdnet_show_inet_routes ();
1096+ //rtems_bsdnet_show_udp_stats (void);
1097+ //rtems_bsdnet_show_tcp_stats (void);
1098
1099 /*
1100 * Run the EPICS startup script
1101@@ -664,5 +776,12 @@
1102 result = main ((sizeof argv / sizeof argv[0]) - 1, argv);
1103 printf ("***** IOC application terminating *****\n");
1104 epicsThreadSleep(1.0);
1105+<<<<<<< TREE
1106 epicsExit(result);
1107+=======
1108+ epicsExit(0);
1109+#if RTEMS_VERSION_INT >= VERSION_INT(4, 11, 99, 0)
1110+ return NULL;
1111+#endif
1112+>>>>>>> MERGE-SOURCE
1113 }
1114
1115=== modified file 'src/libCom/calc/postfix.c'
1116--- src/libCom/calc/postfix.c 2016-05-22 12:38:18 +0000
1117+++ src/libCom/calc/postfix.c 2017-05-01 18:36:52 +0000
1118@@ -27,6 +27,10 @@
1119 #include "postfixPvt.h"
1120 #include "shareLib.h"
1121
1122+#ifdef USE_ALTIVEC
1123+#pragma GCC push_options
1124+#pragma GCC optimize ("O0")
1125+#endif
1126
1127 /* declarations for postfix */
1128
1129@@ -624,3 +628,13 @@
1130 }
1131 }
1132 }
1133+/*
1134+#if __RTEMS_MAJOR__>4 || \
1135+ (__RTEMS_MAJOR__==4 && __RTEMS_MINOR__>11) || \
1136+ (__RTEMS_MAJOR__==4 && __RTEMS_MINOR__==11 && __RTEMS_REVISION__==99)
1137+*/
1138+#ifdef USE_ALTIVEC
1139+#pragma GCC pop_options
1140+#endif
1141+/* #endif */
1142+
1143
1144=== modified file 'src/libCom/error/errlog.c'
1145--- src/libCom/error/errlog.c 2015-08-13 15:44:52 +0000
1146+++ src/libCom/error/errlog.c 2017-05-01 18:36:52 +0000
1147@@ -34,6 +34,10 @@
1148 #include "epicsStdio.h"
1149 #include "epicsExit.h"
1150
1151+#if defined(__rtems__)
1152+#include <rtems/bspIo.h>
1153+#include <rtems.h>
1154+#endif
1155
1156 #define BUFFER_SIZE 1280
1157 #define MAX_MESSAGE_SIZE 256
1158@@ -117,6 +121,7 @@
1159 }
1160
1161 errlogInit(0);
1162+
1163 isOkToBlock = epicsThreadIsOkToBlock();
1164
1165 if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) {
1166
1167=== modified file 'src/libCom/misc/epicsUnitTest.c'
1168--- src/libCom/misc/epicsUnitTest.c 2016-05-22 12:38:18 +0000
1169+++ src/libCom/misc/epicsUnitTest.c 2017-05-01 18:36:52 +0000
1170@@ -248,6 +248,7 @@
1171
1172 void testHarness(void) {
1173 epicsThreadOnce(&onceFlag, testOnce, NULL);
1174+epicsThreadShowAll(1);
1175 epicsAtExit(testHarnessExit, NULL);
1176 Harness = 1;
1177 Programs = 0;
1178
1179=== modified file 'src/libCom/osi/os/Linux/osdSock.h'
1180--- src/libCom/osi/os/Linux/osdSock.h 2017-01-23 23:20:51 +0000
1181+++ src/libCom/osi/os/Linux/osdSock.h 2017-05-01 18:36:52 +0000
1182@@ -26,8 +26,10 @@
1183 #include <arpa/inet.h>
1184 #include <net/if.h>
1185 #include <netdb.h>
1186+#include <ifaddrs.h> /* getifaddrs() */
1187 #include <unistd.h> /* close() and others */
1188
1189+#define USE_IFADDRS
1190
1191 typedef int SOCKET;
1192 #define INVALID_SOCKET (-1)
1193
1194=== added directory 'src/libCom/osi/os/RTEMS-kernel'
1195=== renamed file 'src/libCom/osi/os/RTEMS/devLibVMEOSD.c' => 'src/libCom/osi/os/RTEMS-kernel/devLibVMEOSD.c'
1196=== renamed file 'src/libCom/osi/os/RTEMS/epicsAtomicOSD.cpp' => 'src/libCom/osi/os/RTEMS-kernel/epicsAtomicOSD.cpp'
1197=== renamed file 'src/libCom/osi/os/RTEMS/epicsAtomicOSD.h' => 'src/libCom/osi/os/RTEMS-kernel/epicsAtomicOSD.h'
1198=== renamed file 'src/libCom/osi/os/RTEMS/osdEvent.c' => 'src/libCom/osi/os/RTEMS-kernel/osdEvent.c'
1199=== renamed file 'src/libCom/osi/os/RTEMS/osdEvent.h' => 'src/libCom/osi/os/RTEMS-kernel/osdEvent.h'
1200=== renamed file 'src/libCom/osi/os/RTEMS/osdFindSymbol.c' => 'src/libCom/osi/os/RTEMS-kernel/osdFindSymbol.c'
1201=== renamed file 'src/libCom/osi/os/RTEMS/osdMessageQueue.c' => 'src/libCom/osi/os/RTEMS-kernel/osdMessageQueue.c'
1202=== renamed file 'src/libCom/osi/os/RTEMS/osdMessageQueue.h' => 'src/libCom/osi/os/RTEMS-kernel/osdMessageQueue.h'
1203=== renamed file 'src/libCom/osi/os/RTEMS/osdMutex.c' => 'src/libCom/osi/os/RTEMS-kernel/osdMutex.c'
1204=== renamed file 'src/libCom/osi/os/RTEMS/osdMutex.h' => 'src/libCom/osi/os/RTEMS-kernel/osdMutex.h'
1205=== renamed file 'src/libCom/osi/os/RTEMS/osdPoolStatus.c' => 'src/libCom/osi/os/RTEMS-kernel/osdPoolStatus.c'
1206=== renamed file 'src/libCom/osi/os/RTEMS/osdProcess.c' => 'src/libCom/osi/os/RTEMS-kernel/osdProcess.c'
1207=== renamed file 'src/libCom/osi/os/RTEMS/osdReadline.c' => 'src/libCom/osi/os/RTEMS-kernel/osdReadline.c'
1208=== renamed file 'src/libCom/osi/os/RTEMS/osdSignal.cpp' => 'src/libCom/osi/os/RTEMS-kernel/osdSignal.cpp'
1209=== renamed file 'src/libCom/osi/os/RTEMS/osdSock.h' => 'src/libCom/osi/os/RTEMS-kernel/osdSock.h'
1210=== renamed file 'src/libCom/osi/os/RTEMS/osdSpin.c' => 'src/libCom/osi/os/RTEMS-kernel/osdSpin.c'
1211=== renamed file 'src/libCom/osi/os/RTEMS/osdStrtod.h' => 'src/libCom/osi/os/RTEMS-kernel/osdStrtod.h'
1212=== renamed file 'src/libCom/osi/os/RTEMS/osdThread.c' => 'src/libCom/osi/os/RTEMS-kernel/osdThread.c'
1213=== renamed file 'src/libCom/osi/os/RTEMS/osdThread.h' => 'src/libCom/osi/os/RTEMS-kernel/osdThread.h'
1214=== renamed file 'src/libCom/osi/os/RTEMS/osdThreadExtra.c' => 'src/libCom/osi/os/RTEMS-kernel/osdThreadExtra.c'
1215=== renamed file 'src/libCom/osi/os/RTEMS/osdTime.cpp' => 'src/libCom/osi/os/RTEMS-kernel/osdTime.cpp'
1216=== renamed file 'src/libCom/osi/os/RTEMS/osdTime.h' => 'src/libCom/osi/os/RTEMS-kernel/osdTime.h'
1217=== renamed file 'src/libCom/osi/os/RTEMS/osiUnistd.h' => 'src/libCom/osi/os/RTEMS-kernel/osiUnistd.h'
1218=== added directory 'src/libCom/osi/os/RTEMS-posix'
1219=== added file 'src/libCom/osi/os/RTEMS-posix/devLibVMEOSD.c'
1220--- src/libCom/osi/os/RTEMS-posix/devLibVMEOSD.c 1970-01-01 00:00:00 +0000
1221+++ src/libCom/osi/os/RTEMS-posix/devLibVMEOSD.c 2017-05-01 18:36:52 +0000
1222@@ -0,0 +1,367 @@
1223+/*************************************************************************\
1224+* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
1225+* National Laboratory.
1226+* Copyright (c) 2002 The Regents of the University of California, as
1227+* Operator of Los Alamos National Laboratory.
1228+* Copyright (c) 2017 Fritz-Haber-Institut der Max-Planck-Gesellschaft
1229+* EPICS BASE is distributed subject to a Software License Agreement found
1230+* in file LICENSE that is included with this distribution.
1231+\*************************************************************************/
1232+
1233+/* RTEMS port by Till Straumann, <strauman@slac.stanford.edu>
1234+ * 3/2002
1235+ *
1236+ * Adapted to rtems4.12
1237+ * removed include bsp/bspExt.h
1238+ */
1239+
1240+#include <epicsStdio.h>
1241+#include <epicsExit.h>
1242+#include <rtems.h>
1243+#include <bsp.h>
1244+#include "devLibVME.h"
1245+#include <epicsInterrupt.h>
1246+
1247+#if defined(__PPC__) || defined(__mcf528x__)
1248+
1249+#if defined(__PPC__)
1250+#include <bsp/VME.h>
1251+#endif
1252+
1253+
1254+typedef void myISR (void *pParam);
1255+
1256+static myISR *isrFetch(unsigned vectorNumber, void **parg);
1257+
1258+/*
1259+ * this routine needs to be in the symbol table
1260+ * for this code to work correctly
1261+ */
1262+static void unsolicitedHandlerEPICS(int vectorNumber);
1263+
1264+static myISR *defaultHandlerAddr[]={
1265+ (myISR*)unsolicitedHandlerEPICS,
1266+};
1267+
1268+/*
1269+ * Make sure that the CR/CSR addressing mode is defined.
1270+ * (it may not be in some BSPs).
1271+ */
1272+#ifndef VME_AM_CSR
1273+# define VME_AM_CSR (0x2f)
1274+#endif
1275+
1276+/*
1277+ * we use a translation between an EPICS encoding
1278+ * and a vxWorks encoding here
1279+ * to reduce dependency of drivers on vxWorks
1280+ *
1281+ * we assume that the BSP are configured to use these
1282+ * address modes by default
1283+ */
1284+#define EPICSAddrTypeNoConvert -1
1285+int EPICStovxWorksAddrType[]
1286+ = {
1287+ VME_AM_SUP_SHORT_IO,
1288+ VME_AM_STD_SUP_DATA,
1289+ VME_AM_EXT_SUP_DATA,
1290+ EPICSAddrTypeNoConvert,
1291+ VME_AM_CSR
1292+ };
1293+
1294+/*
1295+ * maps logical address to physical address, but does not detect
1296+ * two device drivers that are using the same address range
1297+ */
1298+static long rtemsDevMapAddr (epicsAddressType addrType, unsigned options,
1299+ size_t logicalAddress, size_t size, volatile void **ppPhysicalAddress);
1300+
1301+/*
1302+ * a bus error safe "wordSize" read at the specified address which returns
1303+ * unsuccessful status if the device isnt present
1304+ */
1305+static long rtemsDevReadProbe (unsigned wordSize, volatile const void *ptr, void *pValue);
1306+
1307+/*
1308+ * a bus error safe "wordSize" write at the specified address which returns
1309+ * unsuccessful status if the device isnt present
1310+ */
1311+static long rtemsDevWriteProbe (unsigned wordSize, volatile void *ptr, const void *pValue);
1312+
1313+static long rtemsDevConnectInterruptVME (
1314+ unsigned vectorNumber,
1315+ void (*pFunction)(),
1316+ void *parameter);
1317+
1318+static long rtemsDevDisconnectInterruptVME (
1319+ unsigned vectorNumber,
1320+ void (*pFunction)()
1321+);
1322+
1323+static long rtemsDevEnableInterruptLevelVME (unsigned level);
1324+
1325+static long rtemsDevDisableInterruptLevelVME (unsigned level);
1326+
1327+static int rtemsDevInterruptInUseVME (unsigned vectorNumber);
1328+
1329+/* RTEMS specific init */
1330+
1331+/*devA24Malloc and devA24Free are not implemented*/
1332+static void *devA24Malloc(size_t size) { return 0;}
1333+static void devA24Free(void *pBlock) {};
1334+static long rtemsDevInit(void);
1335+
1336+/*
1337+ * used by bind in devLib.c
1338+ */
1339+static devLibVME rtemsVirtualOS = {
1340+ rtemsDevMapAddr, rtemsDevReadProbe, rtemsDevWriteProbe,
1341+ rtemsDevConnectInterruptVME, rtemsDevDisconnectInterruptVME,
1342+ rtemsDevEnableInterruptLevelVME, rtemsDevDisableInterruptLevelVME,
1343+ devA24Malloc,devA24Free,rtemsDevInit,rtemsDevInterruptInUseVME
1344+};
1345+devLibVME *pdevLibVME = &rtemsVirtualOS;
1346+
1347+/* RTEMS specific initialization */
1348+static long
1349+rtemsDevInit(void)
1350+{
1351+ /* assume the vme bridge has been initialized by bsp */
1352+ /* init BSP extensions [memProbe etc.] */
1353+ return bspExtInit();
1354+}
1355+
1356+/*
1357+ * devConnectInterruptVME
1358+ *
1359+ * wrapper to minimize driver dependency on OS
1360+ */
1361+static long rtemsDevConnectInterruptVME (
1362+ unsigned vectorNumber,
1363+ void (*pFunction)(),
1364+ void *parameter)
1365+{
1366+ int status;
1367+
1368+
1369+ if (devInterruptInUseVME(vectorNumber)) {
1370+ return S_dev_vectorInUse;
1371+ }
1372+ status = BSP_installVME_isr(
1373+ vectorNumber,
1374+ pFunction,
1375+ parameter);
1376+ if (status) {
1377+ return S_dev_vecInstlFail;
1378+ }
1379+
1380+ return 0;
1381+}
1382+
1383+/*
1384+ *
1385+ * devDisconnectInterruptVME()
1386+ *
1387+ * wrapper to minimize driver dependency on OS
1388+ *
1389+ * The parameter pFunction should be set to the C function pointer that
1390+ * was connected. It is used as a key to prevent a driver from removing
1391+ * an interrupt handler that was installed by another driver
1392+ *
1393+ */
1394+static long rtemsDevDisconnectInterruptVME (
1395+ unsigned vectorNumber,
1396+ void (*pFunction)()
1397+)
1398+{
1399+ void (*psub)();
1400+ void *arg;
1401+ int status;
1402+
1403+ /*
1404+ * If pFunction not connected to this vector
1405+ * then they are probably disconnecting from the wrong vector
1406+ */
1407+ psub = isrFetch(vectorNumber, &arg);
1408+ if(psub != pFunction){
1409+ return S_dev_vectorNotInUse;
1410+ }
1411+
1412+ status = BSP_removeVME_isr(
1413+ vectorNumber,
1414+ psub,
1415+ arg) ||
1416+ BSP_installVME_isr(
1417+ vectorNumber,
1418+ (BSP_VME_ISR_t)unsolicitedHandlerEPICS,
1419+ (void*)vectorNumber);
1420+ if(status){
1421+ return S_dev_vecInstlFail;
1422+ }
1423+
1424+ return 0;
1425+}
1426+
1427+/*
1428+ * enable VME interrupt level
1429+ */
1430+static long rtemsDevEnableInterruptLevelVME (unsigned level)
1431+{
1432+ return BSP_enableVME_int_lvl(level);
1433+}
1434+
1435+/*
1436+ * disable VME interrupt level
1437+ */
1438+static long rtemsDevDisableInterruptLevelVME (unsigned level)
1439+{
1440+ return BSP_disableVME_int_lvl(level);
1441+}
1442+
1443+/*
1444+ * rtemsDevMapAddr ()
1445+ */
1446+static long rtemsDevMapAddr (epicsAddressType addrType, unsigned options,
1447+ size_t logicalAddress, size_t size, volatile void **ppPhysicalAddress)
1448+{
1449+ long status;
1450+
1451+ if (ppPhysicalAddress==NULL) {
1452+ return S_dev_badArgument;
1453+ }
1454+
1455+ if (EPICStovxWorksAddrType[addrType] == EPICSAddrTypeNoConvert)
1456+ {
1457+ *ppPhysicalAddress = (void *) logicalAddress;
1458+ }
1459+ else
1460+ {
1461+ status = BSP_vme2local_adrs(EPICStovxWorksAddrType[addrType],
1462+ logicalAddress, (unsigned long *)ppPhysicalAddress);
1463+ if (status) {
1464+ return S_dev_addrMapFail;
1465+ }
1466+ }
1467+
1468+ return 0;
1469+}
1470+
1471+/*
1472+ * a bus error safe "wordSize" read at the specified address which returns
1473+ * unsuccessful status if the device isnt present
1474+ */
1475+rtems_status_code bspExtMemProbe(void *addr, int write, int size, void *pval);
1476+static long rtemsDevReadProbe (unsigned wordSize, volatile const void *ptr, void *pValue)
1477+{
1478+ long status;
1479+
1480+ /*
1481+ * this global variable exists in the nivxi library
1482+ */
1483+ status = bspExtMemProbe ((void*)ptr, 0/*read*/, wordSize, pValue);
1484+ if (status!=RTEMS_SUCCESSFUL) {
1485+ return S_dev_noDevice;
1486+ }
1487+
1488+ return 0;
1489+}
1490+
1491+/*
1492+ * a bus error safe "wordSize" write at the specified address which returns
1493+ * unsuccessful status if the device isnt present
1494+ */
1495+static long rtemsDevWriteProbe (unsigned wordSize, volatile void *ptr, const void *pValue)
1496+{
1497+ long status;
1498+
1499+ /*
1500+ * this global variable exists in the nivxi library
1501+ */
1502+ status = bspExtMemProbe ((void*)ptr, 1/*write*/, wordSize, (void*)pValue);
1503+ if (status!=RTEMS_SUCCESSFUL) {
1504+ return S_dev_noDevice;
1505+ }
1506+
1507+ return 0;
1508+}
1509+
1510+/*
1511+ * isrFetch()
1512+ */
1513+static myISR *isrFetch(unsigned vectorNumber, void **parg)
1514+{
1515+ /*
1516+ * fetch the handler or C stub attached at this vector
1517+ */
1518+ return (myISR *) BSP_getVME_isr(vectorNumber,parg);
1519+}
1520+
1521+/*
1522+ * determine if a VME interrupt vector is in use
1523+ */
1524+static int rtemsDevInterruptInUseVME (unsigned vectorNumber)
1525+{
1526+ int i;
1527+ myISR *psub;
1528+ void *arg;
1529+
1530+ psub = isrFetch (vectorNumber,&arg);
1531+
1532+ if (!psub)
1533+ return FALSE;
1534+
1535+ /*
1536+ * its a C routine. Does it match a default handler?
1537+ */
1538+ for (i=0; i<NELEMENTS(defaultHandlerAddr); i++) {
1539+ if (defaultHandlerAddr[i] == psub) {
1540+ return FALSE;
1541+ }
1542+ }
1543+
1544+ return TRUE;
1545+}
1546+
1547+
1548+/*
1549+ * unsolicitedHandlerEPICS()
1550+ * what gets called if they disconnect from an
1551+ * interrupt and an interrupt arrives on the
1552+ * disconnected vector
1553+ *
1554+ * NOTE: RTEMS may pass additional arguments - hope
1555+ * this doesn't disturb this handler...
1556+ *
1557+ * A cleaner way would be having a OS dependent
1558+ * macro to declare handler prototypes...
1559+ *
1560+ */
1561+static void unsolicitedHandlerEPICS(int vectorNumber)
1562+{
1563+ /*
1564+ * call epicInterruptContextMessage()
1565+ * and not errMessage()
1566+ * so we are certain that printf()
1567+ * does not get called at interrupt level
1568+ *
1569+ * NOTE: current RTEMS implementation only
1570+ * allows a static string to be passed
1571+ */
1572+ epicsInterruptContextMessage(
1573+ "Interrupt to EPICS disconnected vector"
1574+ );
1575+}
1576+
1577+#endif /* defined(__PPC__) && defined(mpc750) */
1578+
1579+/*
1580+ * Some vxWorks convenience routines
1581+ */
1582+void
1583+bcopyLongs(char *source, char *destination, int nlongs)
1584+{
1585+ const long *s = (long *)source;
1586+ long *d = (long *)destination;
1587+ while(nlongs--)
1588+ *d++ = *s++;
1589+}
1590
1591=== added file 'src/libCom/osi/os/RTEMS-posix/osdInterrupt.c'
1592--- src/libCom/osi/os/RTEMS-posix/osdInterrupt.c 1970-01-01 00:00:00 +0000
1593+++ src/libCom/osi/os/RTEMS-posix/osdInterrupt.c 2017-05-01 18:36:52 +0000
1594@@ -0,0 +1,59 @@
1595+/*************************************************************************\
1596+* Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne
1597+* National Laboratory.
1598+* Copyright (c) 2002 The Regents of the University of California, as
1599+* Operator of Los Alamos National Laboratory.
1600+* EPICS BASE is distributed subject to a Software License Agreement found
1601+* in file LICENSE that is included with this distribution.
1602+\*************************************************************************/
1603+/* osi/default/osdInterrupt.c */
1604+
1605+/* Author: Marty Kraimer Date: 15JUL99 */
1606+
1607+#include <stddef.h>
1608+#include <string.h>
1609+#include <stdlib.h>
1610+#include <stddef.h>
1611+#include <stdio.h>
1612+
1613+#define epicsExportSharedSymbols
1614+#include "epicsMutex.h"
1615+#include "epicsThread.h"
1616+#include "cantProceed.h"
1617+#include "errlog.h"
1618+#include "epicsInterrupt.h"
1619+
1620+#include <rtems/bspIo.h>
1621+#include <rtems.h>
1622+
1623+epicsShareFunc int epicsInterruptLock()
1624+{
1625+ rtems_interrupt_level level;
1626+
1627+ rtems_interrupt_disable (level);
1628+ return level;
1629+}
1630+
1631+epicsShareFunc void epicsInterruptUnlock(int key)
1632+{
1633+ rtems_interrupt_level level = key;
1634+
1635+ rtems_interrupt_enable (level);
1636+}
1637+
1638+epicsShareFunc int epicsInterruptIsInterruptContext()
1639+{
1640+ return rtems_interrupt_is_in_progress ();
1641+}
1642+
1643+epicsShareFunc void epicsInterruptContextMessage(const char *message)
1644+{
1645+ printk("%s", message);
1646+}
1647+
1648+
1649+
1650+
1651+
1652+
1653+
1654
1655=== added file 'src/libCom/osi/os/RTEMS-posix/osdMessageQueue.cpp'
1656--- src/libCom/osi/os/RTEMS-posix/osdMessageQueue.cpp 1970-01-01 00:00:00 +0000
1657+++ src/libCom/osi/os/RTEMS-posix/osdMessageQueue.cpp 2017-05-01 18:36:52 +0000
1658@@ -0,0 +1,163 @@
1659+/*************************************************************************\
1660+* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
1661+* National Laboratory.
1662+* Copyright (c) 2002 The Regents of the University of California, as
1663+* Operator of Los Alamos National Laboratory.
1664+* Copyright (c) 2017 Fritz-Haber-Institut der Max-Planck-Gesellschaft
1665+* EPICS BASE is distributed subject to a Software License Agreement found
1666+* in file LICENSE that is included with this distribution.
1667+\*************************************************************************/
1668+/*
1669+ * Author W. Eric Norum
1670+ * Heinz Junkes
1671+ *
1672+ * Adapted to rtems4.12
1673+ * -> posix message queues
1674+ * remove all internal calls (_xxx), remove e.g. Objects_Locations etc.
1675+ */
1676+
1677+/*
1678+ * We want to access information which is
1679+ * normally hidden from application programs.
1680+ */
1681+#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ 1
1682+
1683+#define epicsExportSharedSymbols
1684+#include <assert.h>
1685+#include <stdio.h>
1686+#include <stdlib.h>
1687+#include <string.h>
1688+#include <rtems.h>
1689+#include <rtems/error.h>
1690+#include "epicsMessageQueue.h"
1691+#include "errlog.h"
1692+#include <epicsAtomic.h>
1693+
1694+#include <errno.h>
1695+#include <mqueue.h>
1696+#include <fcntl.h>
1697+
1698+epicsShareFunc epicsMessageQueueId epicsShareAPI
1699+epicsMessageQueueCreate(unsigned int capacity, unsigned int maximumMessageSize)
1700+{
1701+ struct mq_attr the_attr;
1702+ epicsMessageQueueId id = (epicsMessageQueueId)calloc(1, sizeof(*id));
1703+
1704+ epicsAtomicIncrIntT(&id->idCnt);
1705+ sprintf(id->name, "MQ_%010d",epicsAtomicGetIntT(&id->idCnt));
1706+ the_attr.mq_maxmsg = capacity;
1707+ the_attr.mq_msgsize = maximumMessageSize;
1708+ id->id = mq_open(id->name, O_RDWR | O_CREAT | O_EXCL, 0644, &the_attr);
1709+ if (id->id < 0) {
1710+ errlogPrintf ("Can't create message queue: %s\n", strerror (errno));
1711+ return NULL;
1712+ }
1713+ return id;
1714+}
1715+
1716+epicsShareFunc void epicsShareAPI epicsMessageQueueDestroy(
1717+ epicsMessageQueueId id)
1718+{
1719+ int rv;
1720+ rv = mq_close(id->id);
1721+ if( rv ) {
1722+ errlogPrintf("epicsMessageQueueDestroy mq_close failed: %s\n",
1723+ strerror(rv));
1724+ }
1725+ rv = mq_unlink(id->name);
1726+ if( rv ) {
1727+ errlogPrintf("epicsMessageQueueDestroy mq_unlink %s failed: %s\n",
1728+ id->name, strerror(rv));
1729+ }
1730+ free(id);
1731+}
1732+
1733+epicsShareFunc int epicsShareAPI epicsMessageQueueTrySend(
1734+ epicsMessageQueueId id,
1735+ void *message,
1736+ unsigned int messageSize)
1737+{
1738+ struct timespec ts;
1739+ clock_gettime(CLOCK_REALTIME, &ts);
1740+ return mq_timedsend(id->id, (char const *)message, messageSize, 0, &ts);
1741+}
1742+
1743+epicsShareFunc int epicsShareAPI epicsMessageQueueSendWithTimeout(
1744+ epicsMessageQueueId id,
1745+ void *message,
1746+ unsigned int messageSize,
1747+ double timeout)
1748+{
1749+ struct timespec ts;
1750+ unsigned long micros;
1751+
1752+ // assume timeout in sec
1753+ micros = (unsigned long)(timeout * 1000000.0);
1754+ clock_gettime(CLOCK_REALTIME, &ts);
1755+ ts.tv_sec += micros / 1000000L;
1756+ ts.tv_nsec += (micros % 1000000L) * 1000L;
1757+
1758+ return mq_timedsend (id->id, (const char *)message, messageSize, 0, &ts);
1759+}
1760+
1761+epicsShareFunc int epicsShareAPI epicsMessageQueueTryReceive(
1762+ epicsMessageQueueId id,
1763+ void *message,
1764+ unsigned int size)
1765+{
1766+ struct timespec ts;
1767+ clock_gettime(CLOCK_REALTIME, &ts);
1768+ return mq_timedreceive(id->id, (char *)message, size, NULL, &ts);
1769+}
1770+
1771+epicsShareFunc int epicsShareAPI epicsMessageQueueReceiveWithTimeout(
1772+ epicsMessageQueueId id,
1773+ void *message,
1774+ unsigned int size,
1775+ double timeout)
1776+{
1777+ unsigned long micros;
1778+ struct timespec ts;
1779+
1780+ micros = (unsigned long)(timeout * 1000000.0);
1781+ clock_gettime(CLOCK_REALTIME, &ts);
1782+ ts.tv_sec += micros / 1000000L;
1783+ ts.tv_nsec += (micros % 1000000L) * 1000L;
1784+
1785+ return mq_timedreceive(id->id, (char *)message, size, NULL, &ts);
1786+}
1787+
1788+epicsShareFunc int epicsShareAPI epicsMessageQueuePending(
1789+ epicsMessageQueueId id)
1790+{
1791+ int rv;
1792+ struct mq_attr the_attr;
1793+
1794+ rv = mq_getattr(id->id, &the_attr);
1795+ if (rv) {
1796+ errlogPrintf("Epics Message queue %x (%s) get attr failed: %s\n",
1797+ (unsigned int)id->id, id->name, strerror(rv));
1798+ return -1;
1799+ }
1800+ return the_attr.mq_curmsgs;
1801+}
1802+
1803+epicsShareFunc void epicsShareAPI epicsMessageQueueShow(
1804+ epicsMessageQueueId id,
1805+ int level)
1806+{
1807+ int rv;
1808+ struct mq_attr the_attr;
1809+
1810+ rv = mq_getattr(id->id, &the_attr);
1811+ if (rv) {
1812+ errlogPrintf("Epics Message queue %x (%s) get attr failed: %s\n",
1813+ (unsigned int)id->id, id->id, strerror(rv));
1814+ }
1815+
1816+ printf("Message Queue Used:%ld Max Msg:%lu", the_attr.mq_curmsgs, the_attr.mq_maxmsg);
1817+ if (level >= 1)
1818+ printf(" Maximum size:%lu", the_attr.mq_msgsize);
1819+
1820+ printf("\n");
1821+}
1822
1823=== added file 'src/libCom/osi/os/RTEMS-posix/osdMessageQueue.h'
1824--- src/libCom/osi/os/RTEMS-posix/osdMessageQueue.h 1970-01-01 00:00:00 +0000
1825+++ src/libCom/osi/os/RTEMS-posix/osdMessageQueue.h 2017-05-01 18:36:52 +0000
1826@@ -0,0 +1,31 @@
1827+/*************************************************************************\
1828+ * * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
1829+ * * National Laboratory.
1830+ * * Copyright (c) 2002 The Regents of the University of California, as
1831+ * * Operator of Los Alamos National Laboratory.
1832+ * * Copyright (c) 2017 Fritz-Haber-Institut der Max-Planck-Gesellschaft
1833+ * * EPICS BASE is distributed subject to a Software License Agreement found
1834+ * * in file LICENSE that is included with this distribution.
1835+ * \*************************************************************************/
1836+/*
1837+ * Author W. Eric Norum
1838+ * Heinz Junkes
1839+ *
1840+ * Eric's note : Very thin shims around vxWorks routines
1841+ *
1842+ * Adapted to rtems4.12
1843+ * -> posix message queues
1844+ */
1845+
1846+#include <rtems.h>
1847+#include <mqueue.h>
1848+
1849+struct epicsMessageQueueOSD {
1850+ mqd_t id;
1851+ char name[24];
1852+ int idCnt;
1853+
1854+};
1855+
1856+#define epicsMessageQueueSend(q,m,l) (mq_send((q)->id, (const char*)(m), (l), 0))
1857+#define epicsMessageQueueReceive(q,m,s) (mq_receive((q)->id, (char*)(m), (s), NULL))
1858
1859=== added file 'src/libCom/osi/os/RTEMS-posix/osdMutex.c'
1860--- src/libCom/osi/os/RTEMS-posix/osdMutex.c 1970-01-01 00:00:00 +0000
1861+++ src/libCom/osi/os/RTEMS-posix/osdMutex.c 2017-05-01 18:36:52 +0000
1862@@ -0,0 +1,6 @@
1863+#include <rtems.h>
1864+#include <rtems/error.h>
1865+#include <rtems/rtems/tasks.h>
1866+#include <rtems/score/threadimpl.h>
1867+
1868+#include "../posix/osdMutex.c"
1869
1870=== added file 'src/libCom/osi/os/RTEMS-posix/osdPoolStatus.c'
1871--- src/libCom/osi/os/RTEMS-posix/osdPoolStatus.c 1970-01-01 00:00:00 +0000
1872+++ src/libCom/osi/os/RTEMS-posix/osdPoolStatus.c 2017-05-01 18:36:52 +0000
1873@@ -0,0 +1,34 @@
1874+/*************************************************************************\
1875+* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
1876+* National Laboratory.
1877+* Copyright (c) 2002 The Regents of the University of California, as
1878+* Operator of Los Alamos National Laboratory.
1879+* Copyright (c) 2017 Fritz-Haber-Institut der Max-Planck-Gesellschaft
1880+* EPICS BASE is distributed subject to a Software License Agreement found
1881+* in file LICENSE that is included with this distribution.
1882+\*************************************************************************/
1883+
1884+/*
1885+ * Heinz Junkes
1886+ * Adapted to rtems4.12
1887+ */
1888+
1889+#include <rtems.h>
1890+#include <rtems/malloc.h>
1891+#include <rtems/score/heap.h>
1892+#define epicsExportSharedSymbols
1893+#include "osiPoolStatus.h"
1894+
1895+/*
1896+ * osiSufficentSpaceInPool ()
1897+ *
1898+ */
1899+epicsShareFunc int epicsShareAPI osiSufficentSpaceInPool ( size_t contiguousBlockSize )
1900+{
1901+ unsigned long n;
1902+ Heap_Information_block info;
1903+
1904+ malloc_info( &info );
1905+ n = info.Stats.size - (unsigned long)(info.Stats.lifetime_allocated - info.Stats.lifetime_freed);
1906+ return (n > (50000 + contiguousBlockSize));
1907+}
1908
1909=== added file 'src/libCom/osi/os/RTEMS-posix/osdSock.h'
1910--- src/libCom/osi/os/RTEMS-posix/osdSock.h 1970-01-01 00:00:00 +0000
1911+++ src/libCom/osi/os/RTEMS-posix/osdSock.h 2017-05-01 18:36:52 +0000
1912@@ -0,0 +1,111 @@
1913+/*************************************************************************\
1914+* Copyright (c) 2002 The University of Saskatchewan
1915+* Copyright (c) 2017 Fritz-Haber-Institut der Max-Planck-Gesellschaft
1916+* EPICS BASE is distributed subject to a Software License Agreement found
1917+* in file LICENSE that is included with this distribution.
1918+\*************************************************************************/
1919+/*
1920+ * RTEMS osdSock.h
1921+ * Author: W. Eric Norum
1922+ * Heinz Junkes
1923+ *
1924+ * Adapted to rtems4.12
1925+ */
1926+#ifndef osdSockH
1927+#define osdSockH
1928+
1929+#include <errno.h>
1930+
1931+#include <sys/types.h>
1932+#include <sys/param.h>
1933+#include <sys/time.h>
1934+#include <sys/socket.h>
1935+#include <sys/ioctl.h>
1936+#include <netinet/in.h>
1937+#include <netinet/tcp.h>
1938+#include <arpa/inet.h>
1939+#include <net/if.h>
1940+#include <netdb.h>
1941+#include <ifaddrs.h> /* getifaddrs() */
1942+#include <unistd.h>
1943+
1944+#ifdef __cplusplus
1945+extern "C" {
1946+#endif
1947+
1948+int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
1949+
1950+#ifdef __cplusplus
1951+}
1952+#endif
1953+
1954+
1955+#ifndef IPPORT_USERRESERVED
1956+#define IPPORT_USERRESERVED 5000
1957+#endif
1958+
1959+#define USE_IFADDRS
1960+
1961+typedef int SOCKET;
1962+#define INVALID_SOCKET (-1)
1963+#define SOCKERRNO errno
1964+#define socket_ioctl(A,B,C) ioctl(A,B,C)
1965+typedef int osiSockIoctl_t;
1966+typedef socklen_t osiSocklen_t;
1967+
1968+#define FD_IN_FDSET(FD) ((FD)<FD_SETSIZE)
1969+
1970+#define SOCK_EWOULDBLOCK EWOULDBLOCK
1971+#define SOCK_ENOBUFS ENOBUFS
1972+#define SOCK_ECONNRESET ECONNRESET
1973+#define SOCK_ETIMEDOUT ETIMEDOUT
1974+#define SOCK_EADDRINUSE EADDRINUSE
1975+#define SOCK_EADDRNOTAVAIL EADDRNOTAVAIL
1976+#define SOCK_ECONNREFUSED ECONNREFUSED
1977+#define SOCK_ECONNABORTED ECONNABORTED
1978+#define SOCK_EINPROGRESS EINPROGRESS
1979+#define SOCK_EISCONN EISCONN
1980+#define SOCK_EALREADY EALREADY
1981+#define SOCK_EINVAL EINVAL
1982+#define SOCK_EINTR EINTR
1983+#define SOCK_EPIPE EPIPE
1984+#define SOCK_EMFILE EMFILE
1985+#define SOCK_SHUTDOWN EPIPE
1986+#define SOCK_ENOTSOCK ENOTSOCK
1987+#define SOCK_EBADF EBADF
1988+
1989+// already defined in newlib
1990+//#define bzero(p,n) memset(p,0,n)
1991+#include <sys/time.h>
1992+#include <sys/types.h>
1993+#include <unistd.h>
1994+
1995+#ifndef INADDR_LOOPBACK
1996+#define INADDR_LOOPBACK (u_long)0x7F000001
1997+#endif
1998+
1999+#ifndef INADDR_NONE
2000+# define INADDR_NONE (0xffffffff)
2001+#endif
2002+
2003+/*
2004+ * For shutdown()
2005+ */
2006+#ifndef SHUT_RD
2007+# define SHUT_RD 0
2008+#endif
2009+
2010+#ifndef SHUT_WR
2011+# define SHUT_WR 1
2012+#endif
2013+
2014+#ifndef SHUT_RDWR
2015+# define SHUT_RDWR 2
2016+#endif
2017+
2018+/*
2019+ * Ensure that we get the right network code in default/osdNetIntf.c.
2020+ */
2021+#define ifreq_size(pifreq) (pifreq->ifr_addr.sa_len + sizeof(pifreq->ifr_name))
2022+
2023+#endif /*osdSockH*/
2024
2025=== modified file 'src/libCom/osi/os/WIN32/osdNetIntf.c'
2026--- src/libCom/osi/os/WIN32/osdNetIntf.c 2017-02-01 17:57:04 +0000
2027+++ src/libCom/osi/os/WIN32/osdNetIntf.c 2017-05-01 18:36:52 +0000
2028@@ -3,6 +3,8 @@
2029 * National Laboratory.
2030 * Copyright (c) 2002 The Regents of the University of California, as
2031 * Operator of Los Alamos National Laboratory.
2032+* Copyright (c) 2015 Brookhaven Science Associates as Operator of
2033+* Brookhaven National Lab.
2034 * EPICS BASE is distributed subject to a Software License Agreement found
2035 * in file LICENSE that is included with this distribution.
2036 \*************************************************************************/
2037@@ -40,214 +42,110 @@
2038 #include "epicsThread.h"
2039 #include "epicsVersion.h"
2040
2041-static osiSockAddr osiLocalAddrResult;
2042-static epicsThreadOnceId osiLocalAddrId = EPICS_THREAD_ONCE_INIT;
2043-
2044-/*
2045- * osiLocalAddr ()
2046- */
2047 static void osiLocalAddrOnce ( void *raw )
2048 {
2049- SOCKET *psocket = raw;
2050- osiSockAddr addr;
2051- int status;
2052- INTERFACE_INFO *pIfinfo;
2053- INTERFACE_INFO *pIfinfoList = NULL;
2054- unsigned nelem;
2055- DWORD numifs;
2056- DWORD cbBytesReturned;
2057-
2058- memset ( (void *) &addr, '\0', sizeof ( addr ) );
2059- addr.sa.sa_family = AF_UNSPEC;
2060-
2061- /* only valid for winsock 2 and above */
2062- if ( wsaMajorVersion() < 2 ) {
2063- goto fail;
2064- }
2065-
2066- nelem = 100;
2067- pIfinfoList = (INTERFACE_INFO *) calloc ( nelem, sizeof (INTERFACE_INFO) );
2068- if (!pIfinfoList) {
2069- errlogPrintf ("calloc failed\n");
2070- goto fail;
2071- }
2072-
2073- status = WSAIoctl (*psocket, SIO_GET_INTERFACE_LIST, NULL, 0,
2074- (LPVOID)pIfinfoList, nelem*sizeof(INTERFACE_INFO),
2075- &cbBytesReturned, NULL, NULL);
2076-
2077- if (status != 0 || cbBytesReturned == 0) {
2078- errlogPrintf ("WSAIoctl SIO_GET_INTERFACE_LIST failed %d\n",WSAGetLastError());
2079- goto fail;
2080- }
2081-
2082- numifs = cbBytesReturned / sizeof(INTERFACE_INFO);
2083- for (pIfinfo = pIfinfoList; pIfinfo < (pIfinfoList+numifs); pIfinfo++){
2084-
2085- /*
2086- * dont use interfaces that have been disabled
2087- */
2088- if (!(pIfinfo->iiFlags & IFF_UP)) {
2089- continue;
2090- }
2091-
2092- /*
2093- * dont use the loop back interface
2094- */
2095- if (pIfinfo->iiFlags & IFF_LOOPBACK) {
2096- continue;
2097- }
2098-
2099- addr.sa = pIfinfo->iiAddress.Address;
2100-
2101- /* Work around MS Winsock2 bugs */
2102- if (addr.sa.sa_family == 0) {
2103- addr.sa.sa_family = AF_INET;
2104- }
2105-
2106- osiLocalAddrResult = addr;
2107- free ( pIfinfoList );
2108- return;
2109- }
2110-
2111- errlogPrintf (
2112- "osiLocalAddr(): only loopback found\n");
2113-fail:
2114- /* fallback to loopback */
2115- memset ( (void *) &addr, '\0', sizeof ( addr ) );
2116- addr.ia.sin_family = AF_INET;
2117- addr.ia.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
2118- osiLocalAddrResult = addr;
2119-
2120- free ( pIfinfoList );
2121-}
2122-
2123-epicsShareFunc osiSockAddr epicsShareAPI osiLocalAddr (SOCKET socket)
2124-{
2125- epicsThreadOnce(&osiLocalAddrId, osiLocalAddrOnce, (void*)&socket);
2126- return osiLocalAddrResult;
2127-}
2128-
2129-/*
2130- * osiSockDiscoverBroadcastAddresses ()
2131- */
2132-epicsShareFunc void epicsShareAPI osiSockDiscoverBroadcastAddresses
2133- (ELLLIST *pList, SOCKET socket, const osiSockAddr *pMatchAddr)
2134-{
2135- int status;
2136- INTERFACE_INFO *pIfinfo;
2137- INTERFACE_INFO *pIfinfoList;
2138- unsigned nelem;
2139- int numifs;
2140- DWORD cbBytesReturned;
2141- osiSockAddrNode *pNewNode;
2142-
2143- if ( pMatchAddr->sa.sa_family == AF_INET ) {
2144- if ( pMatchAddr->ia.sin_addr.s_addr == htonl (INADDR_LOOPBACK) ) {
2145- pNewNode = (osiSockAddrNode *) calloc (1, sizeof (*pNewNode) );
2146- if ( pNewNode == NULL ) {
2147- return;
2148- }
2149- pNewNode->addr.ia.sin_family = AF_INET;
2150- pNewNode->addr.ia.sin_port = htons ( 0 );
2151- pNewNode->addr.ia.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
2152- ellAdd ( pList, &pNewNode->node );
2153- return;
2154- }
2155- }
2156+int ret = -1, status, foundlo = 0;
2157+ SOCKET sock;
2158+ unsigned nelem = 10, i;
2159+ INTERFACE_INFO *info = NULL;
2160+ DWORD cbBytesReturned;
2161
2162 /* only valid for winsock 2 and above */
2163 if (wsaMajorVersion() < 2 ) {
2164- fprintf(stderr, "Need to set EPICS_CA_AUTO_ADDR_LIST=NO for winsock 1\n");
2165- return;
2166- }
2167-
2168- nelem = 100;
2169- pIfinfoList = (INTERFACE_INFO *) calloc(nelem, sizeof(INTERFACE_INFO));
2170- if(!pIfinfoList){
2171- return;
2172- }
2173-
2174- status = WSAIoctl (socket, SIO_GET_INTERFACE_LIST,
2175- NULL, 0,
2176- (LPVOID)pIfinfoList, nelem*sizeof(INTERFACE_INFO),
2177- &cbBytesReturned, NULL, NULL);
2178+ fprintf(stderr, "Interface discovery not supported for winsock 1\n"
2179+ "Need to set EPICS_CA_AUTO_ADDR_LIST=NO\n");
2180+ return ret;
2181+ }
2182+
2183+ sock = epicsSocketCreate(AF_INET, SOCK_DGRAM, 0);
2184+ if(sock==INVALID_SOCKET)
2185+ return ret;
2186+
2187+ info = calloc(nelem, sizeof(*info));
2188+ if(!info)
2189+ goto cleanup;
2190+
2191+ /* In future use SIO_GET_INTERFACE_LIST_EX to include IPv6 */
2192+
2193+ status = WSAIoctl (sock, SIO_GET_INTERFACE_LIST,
2194+ NULL, 0,
2195+ (LPVOID)info, nelem*sizeof(*info),
2196+ &cbBytesReturned, NULL, NULL);
2197
2198 if (status != 0 || cbBytesReturned == 0) {
2199 fprintf(stderr, "WSAIoctl SIO_GET_INTERFACE_LIST failed %d\n",WSAGetLastError());
2200- free(pIfinfoList);
2201- return;
2202- }
2203-
2204- numifs = cbBytesReturned/sizeof(INTERFACE_INFO);
2205- for (pIfinfo = pIfinfoList; pIfinfo < (pIfinfoList+numifs); pIfinfo++){
2206-
2207- /*
2208- * dont bother with interfaces that have been disabled
2209- */
2210- if (!(pIfinfo->iiFlags & IFF_UP)) {
2211- continue;
2212- }
2213-
2214- if (pIfinfo->iiFlags & IFF_LOOPBACK) {
2215- continue;
2216- }
2217-
2218- /*
2219- * work around WS2 bug
2220- */
2221- if (pIfinfo->iiAddress.Address.sa_family != AF_INET) {
2222- if (pIfinfo->iiAddress.Address.sa_family == 0) {
2223- pIfinfo->iiAddress.Address.sa_family = AF_INET;
2224- }
2225- }
2226-
2227- /*
2228- * if it isnt a wildcarded interface then look for
2229- * an exact match
2230- */
2231- if (pMatchAddr->sa.sa_family != AF_UNSPEC) {
2232- if (pIfinfo->iiAddress.Address.sa_family != pMatchAddr->sa.sa_family) {
2233- continue;
2234- }
2235- if (pIfinfo->iiAddress.Address.sa_family != AF_INET) {
2236- continue;
2237- }
2238- if (pMatchAddr->sa.sa_family != AF_INET) {
2239- continue;
2240- }
2241- if (pMatchAddr->ia.sin_addr.s_addr != htonl(INADDR_ANY)) {
2242- if (pIfinfo->iiAddress.AddressIn.sin_addr.s_addr != pMatchAddr->ia.sin_addr.s_addr) {
2243- continue;
2244- }
2245- }
2246- }
2247-
2248- pNewNode = (osiSockAddrNode *) calloc (1, sizeof(*pNewNode));
2249- if (pNewNode==NULL) {
2250- errlogPrintf ("osiSockDiscoverBroadcastAddresses(): no memory available for configuration\n");
2251- return;
2252- }
2253-
2254- if (pIfinfo->iiAddress.Address.sa_family == AF_INET &&
2255- pIfinfo->iiFlags & IFF_BROADCAST) {
2256- const unsigned mask = pIfinfo->iiNetmask.AddressIn.sin_addr.s_addr;
2257- const unsigned bcast = pIfinfo->iiBroadcastAddress.AddressIn.sin_addr.s_addr;
2258- const unsigned addr = pIfinfo->iiAddress.AddressIn.sin_addr.s_addr;
2259- unsigned result = (addr & mask) | (bcast &~mask);
2260- pNewNode->addr.ia.sin_family = AF_INET;
2261- pNewNode->addr.ia.sin_addr.s_addr = result;
2262- pNewNode->addr.ia.sin_port = htons ( 0 );
2263- }
2264- else {
2265- pNewNode->addr.sa = pIfinfo->iiBroadcastAddress.Address;
2266- }
2267-
2268- /*
2269- * LOCK applied externally
2270- */
2271- ellAdd (pList, &pNewNode->node);
2272- }
2273-
2274- free (pIfinfoList);
2275+ goto cleanup;
2276+ }
2277+
2278+ nelem = cbBytesReturned/sizeof(*info);
2279+
2280+ for(i=0; i<nelem; i++)
2281+ {
2282+ unsigned int flags;
2283+ osiInterfaceInfo *node = calloc(1, sizeof(*node));
2284+ if(!node)
2285+ goto cleanup;
2286+
2287+ /* work around WS2 bug */
2288+ if(info[i].iiAddress.AddressIn.sin_family==0)
2289+ info[i].iiAddress.AddressIn.sin_family = AF_INET;
2290+
2291+ if(info[i].iiAddress.AddressIn.sin_family!=AF_INET) {
2292+ free(node);
2293+ continue;
2294+ }
2295+
2296+ node->address.ia = info[i].iiAddress.AddressIn;
2297+ node->netmask.ia = info[i].iiNetmask.AddressIn;
2298+ node->endpoint.ia = info[i].iiBroadcastAddress.AddressIn;
2299+
2300+ flags = info[i].iiFlags;
2301+
2302+ if(flags&IFF_UP) node->up = 1;
2303+ if(flags&IFF_BROADCAST) node->broadcast = 1;
2304+ if(flags&IFF_MULTICAST) node->multicast = 1;
2305+ if(flags&IFF_LOOPBACK) node->loopback = 1;
2306+ /* BSD sockets have IFF_POINTOPOINT while winsock has IFF_POINTTOPOINT
2307+ * Note the extra 'T'
2308+ */
2309+ if(flags&IFF_POINTTOPOINT) node->point2point = 1;
2310+
2311+ if(node->broadcast && node->point2point) {
2312+ errlogPrintf("Interface %u claims both broadcast and point to point,"
2313+ " which should not be possible. Assuming broadcast only.",
2314+ i);
2315+ node->point2point = 0;
2316+ }
2317+
2318+ if(node->loopback) foundlo = 1;
2319+ ellAdd(pList, &node->node);
2320+ }
2321+
2322+ if(!foundlo) {
2323+ /* sometimes the loopback isn't included (WINE+mingw) */
2324+ osiInterfaceInfo *node = calloc(1, sizeof(*node));
2325+ if(!node)
2326+ goto cleanup;
2327+
2328+ node->up = 1;
2329+ node->loopback = 1;
2330+
2331+ node->address.ia.sin_family = AF_INET;
2332+ node->address.ia.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
2333+ node->address.ia.sin_port = 0;
2334+
2335+ node->netmask.ia.sin_family = AF_INET;
2336+ node->netmask.ia.sin_addr.s_addr = htonl(0xff000000);
2337+ node->netmask.ia.sin_port = 0;
2338+
2339+ ellInsert(pList, NULL, &node->node);
2340+ }
2341+
2342+ ret = 0;
2343+cleanup:
2344+ if(ret)
2345+ ellFree(pList);
2346+ free(info);
2347+ epicsSocketDestroy(sock);
2348+ return ret;
2349 }
2350
2351=== modified file 'src/libCom/osi/os/default/osdNetIntf.c'
2352--- src/libCom/osi/os/default/osdNetIntf.c 2017-02-01 17:57:04 +0000
2353+++ src/libCom/osi/os/default/osdNetIntf.c 2017-05-01 18:36:52 +0000
2354@@ -3,6 +3,8 @@
2355 * National Laboratory.
2356 * Copyright (c) 2002 The Regents of the University of California, as
2357 * Operator of Los Alamos National Laboratory.
2358+* Copyright (c) 2015 Brookhaven Science Associates as Operator of
2359+* Brookhaven National Lab.
2360 * EPICS BASE Versions 3.13.7
2361 * and higher are distributed subject to a Software License Agreement found
2362 * in file LICENSE that is included with this distribution.
2363@@ -19,6 +21,7 @@
2364 #include <stdlib.h>
2365
2366 #define epicsExportSharedSymbols
2367+#include "dbDefs.h"
2368 #include "osiSock.h"
2369 #include "epicsAssert.h"
2370 #include "errlog.h"
2371@@ -30,323 +33,155 @@
2372 # define ifDepenDebugPrintf(argsInParen)
2373 #endif
2374
2375-static osiSockAddr osiLocalAddrResult;
2376-static epicsThreadOnceId osiLocalAddrId = EPICS_THREAD_ONCE_INIT;
2377-
2378-/*
2379- * Determine the size of an ifreq structure
2380- * Made difficult by the fact that addresses larger than the structure
2381- * size may be returned from the kernel.
2382- */
2383-static size_t ifreqSize ( struct ifreq *pifreq )
2384-{
2385- size_t size;
2386-
2387- size = ifreq_size ( pifreq );
2388- if ( size < sizeof ( *pifreq ) ) {
2389- size = sizeof ( *pifreq );
2390- }
2391- return size;
2392-}
2393-
2394-/*
2395- * Move to the next ifreq structure
2396- */
2397-static struct ifreq * ifreqNext ( struct ifreq *pifreq )
2398-{
2399- struct ifreq *ifr;
2400-
2401- ifr = ( struct ifreq * )( ifreqSize (pifreq) + ( char * ) pifreq );
2402- ifDepenDebugPrintf( ("ifreqNext() pifreq %p, size 0x%x, ifr 0x%p\n", pifreq, (unsigned)ifreqSize (pifreq), ifr) );
2403- return ifr;
2404-}
2405-
2406-
2407-/*
2408- * osiSockDiscoverBroadcastAddresses ()
2409- */
2410-epicsShareFunc void epicsShareAPI osiSockDiscoverBroadcastAddresses
2411- (ELLLIST *pList, SOCKET socket, const osiSockAddr *pMatchAddr)
2412-{
2413- static const unsigned nelem = 100;
2414- int status;
2415- struct ifconf ifconf;
2416- struct ifreq *pIfreqList;
2417- struct ifreq *pIfreqListEnd;
2418- struct ifreq *pifreq;
2419- struct ifreq *pnextifreq;
2420- osiSockAddrNode *pNewNode;
2421-
2422- if ( pMatchAddr->sa.sa_family == AF_INET ) {
2423- if ( pMatchAddr->ia.sin_addr.s_addr == htonl (INADDR_LOOPBACK) ) {
2424- pNewNode = (osiSockAddrNode *) calloc (1, sizeof (*pNewNode) );
2425- if ( pNewNode == NULL ) {
2426- errlogPrintf ( "osiSockDiscoverBroadcastAddresses(): no memory available for configuration\n" );
2427- return;
2428- }
2429- pNewNode->addr.ia.sin_family = AF_INET;
2430- pNewNode->addr.ia.sin_port = htons ( 0 );
2431- pNewNode->addr.ia.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
2432- ellAdd ( pList, &pNewNode->node );
2433- return;
2434- }
2435- }
2436-
2437- /*
2438- * use pool so that we avoid using too much stack space
2439- *
2440- * nelem is set to the maximum interfaces
2441- * on one machine here
2442- */
2443- pIfreqList = (struct ifreq *) calloc ( nelem, sizeof(*pifreq) );
2444- if (!pIfreqList) {
2445- errlogPrintf ("osiSockDiscoverBroadcastAddresses(): no memory to complete request\n");
2446- return;
2447- }
2448-
2449- ifconf.ifc_len = nelem * sizeof(*pifreq);
2450- ifconf.ifc_req = pIfreqList;
2451- status = socket_ioctl (socket, SIOCGIFCONF, &ifconf);
2452- if (status < 0 || ifconf.ifc_len == 0) {
2453- errlogPrintf ("osiSockDiscoverBroadcastAddresses(): unable to fetch network interface configuration (%d)\n", status);
2454- free (pIfreqList);
2455- return;
2456- }
2457-
2458- pIfreqListEnd = (struct ifreq *) (ifconf.ifc_len + (char *) pIfreqList);
2459- pIfreqListEnd--;
2460-
2461- for ( pifreq = pIfreqList; pifreq <= pIfreqListEnd; pifreq = pnextifreq ) {
2462- uint32_t current_ifreqsize;
2463-
2464- /*
2465- * find the next ifreq
2466- */
2467- pnextifreq = ifreqNext (pifreq);
2468-
2469- /* determine ifreq size */
2470- current_ifreqsize = ifreqSize ( pifreq );
2471- /* copy current ifreq to aligned bufferspace (to start of pIfreqList buffer) */
2472- memmove(pIfreqList, pifreq, current_ifreqsize);
2473-
2474- ifDepenDebugPrintf (("osiSockDiscoverBroadcastAddresses(): found IFACE: %s len: 0x%x current_ifreqsize: 0x%x \n",
2475- pIfreqList->ifr_name,
2476- (unsigned)ifreq_size(pifreq),
2477- (unsigned)current_ifreqsize));
2478-
2479- /*
2480- * If its not an internet interface then dont use it
2481- */
2482- if ( pIfreqList->ifr_addr.sa_family != AF_INET ) {
2483- ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): interface \"%s\" was not AF_INET\n", pIfreqList->ifr_name) );
2484- continue;
2485- }
2486-
2487- /*
2488- * if it isnt a wildcarded interface then look for
2489- * an exact match
2490- */
2491- if ( pMatchAddr->sa.sa_family != AF_UNSPEC ) {
2492- if ( pMatchAddr->sa.sa_family != AF_INET ) {
2493- continue;
2494- }
2495- if ( pMatchAddr->ia.sin_addr.s_addr != htonl (INADDR_ANY) ) {
2496- struct sockaddr_in *pInetAddr = (struct sockaddr_in *) &pIfreqList->ifr_addr;
2497- if ( pInetAddr->sin_addr.s_addr != pMatchAddr->ia.sin_addr.s_addr ) {
2498- ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\" didnt match\n", pIfreqList->ifr_name) );
2499- continue;
2500- }
2501- }
2502- }
2503-
2504- status = socket_ioctl ( socket, SIOCGIFFLAGS, pIfreqList );
2505- if ( status ) {
2506- errlogPrintf ("osiSockDiscoverBroadcastAddresses(): net intf flags fetch for \"%s\" failed\n", pIfreqList->ifr_name);
2507- continue;
2508- }
2509- ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\" flags: %x\n", pIfreqList->ifr_name, pIfreqList->ifr_flags) );
2510-
2511- /*
2512- * dont bother with interfaces that have been disabled
2513- */
2514- if ( ! ( pIfreqList->ifr_flags & IFF_UP ) ) {
2515- ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\" was down\n", pIfreqList->ifr_name) );
2516- continue;
2517- }
2518-
2519- /*
2520- * dont use the loop back interface
2521- */
2522- if ( pIfreqList->ifr_flags & IFF_LOOPBACK ) {
2523- ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): ignoring loopback interface: \"%s\"\n", pIfreqList->ifr_name) );
2524- continue;
2525- }
2526-
2527- pNewNode = (osiSockAddrNode *) calloc (1, sizeof (*pNewNode) );
2528- if ( pNewNode == NULL ) {
2529- errlogPrintf ( "osiSockDiscoverBroadcastAddresses(): no memory available for configuration\n" );
2530- free ( pIfreqList );
2531- return;
2532- }
2533-
2534- /*
2535- * If this is an interface that supports
2536- * broadcast fetch the broadcast address.
2537- *
2538- * Otherwise if this is a point to point
2539- * interface then use the destination address.
2540- *
2541- * Otherwise CA will not query through the
2542- * interface.
2543- */
2544- if ( pIfreqList->ifr_flags & IFF_BROADCAST ) {
2545- osiSockAddr baddr;
2546- status = socket_ioctl (socket, SIOCGIFBRDADDR, pIfreqList);
2547- if ( status ) {
2548- errlogPrintf ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\": bcast addr fetch fail\n", pIfreqList->ifr_name);
2549- free ( pNewNode );
2550- continue;
2551- }
2552- baddr.sa = pIfreqList->ifr_broadaddr;
2553- if (baddr.ia.sin_family==AF_INET && baddr.ia.sin_addr.s_addr != INADDR_ANY) {
2554- pNewNode->addr.sa = pIfreqList->ifr_broadaddr;
2555- ifDepenDebugPrintf ( ( "found broadcast addr = %x\n", ntohl ( baddr.ia.sin_addr.s_addr ) ) );
2556- } else {
2557- ifDepenDebugPrintf ( ( "Ignoring broadcast addr = \n", ntohl ( baddr.ia.sin_addr.s_addr ) ) );
2558- free ( pNewNode );
2559- continue;
2560- }
2561- }
2562-#if defined (IFF_POINTOPOINT)
2563- else if ( pIfreqList->ifr_flags & IFF_POINTOPOINT ) {
2564- status = socket_ioctl ( socket, SIOCGIFDSTADDR, pIfreqList);
2565- if ( status ) {
2566- ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\": pt to pt addr fetch fail\n", pIfreqList->ifr_name) );
2567- free ( pNewNode );
2568- continue;
2569- }
2570- pNewNode->addr.sa = pIfreqList->ifr_dstaddr;
2571- }
2572-#endif
2573- else {
2574- ifDepenDebugPrintf ( ( "osiSockDiscoverBroadcastAddresses(): net intf \"%s\": not point to point or bcast?\n", pIfreqList->ifr_name ) );
2575- free ( pNewNode );
2576- continue;
2577- }
2578-
2579- ifDepenDebugPrintf ( ("osiSockDiscoverBroadcastAddresses(): net intf \"%s\" found\n", pIfreqList->ifr_name) );
2580-
2581- /*
2582- * LOCK applied externally
2583- */
2584- ellAdd ( pList, &pNewNode->node );
2585- }
2586-
2587- free ( pIfreqList );
2588-}
2589-
2590-/*
2591- * osiLocalAddr ()
2592- */
2593-static void osiLocalAddrOnce (void *raw)
2594-{
2595- SOCKET *psocket = raw;
2596- const unsigned nelem = 100;
2597- osiSockAddr addr;
2598- int status;
2599- struct ifconf ifconf;
2600- struct ifreq *pIfreqList;
2601- struct ifreq *pifreq;
2602- struct ifreq *pIfreqListEnd;
2603- struct ifreq *pnextifreq;
2604-
2605- memset ( (void *) &addr, '\0', sizeof ( addr ) );
2606- addr.sa.sa_family = AF_UNSPEC;
2607-
2608- pIfreqList = (struct ifreq *) calloc ( nelem, sizeof(*pIfreqList) );
2609- if ( ! pIfreqList ) {
2610- errlogPrintf ( "osiLocalAddr(): no memory to complete request\n" );
2611- goto fail;
2612- }
2613-
2614- ifconf.ifc_len = nelem * sizeof ( *pIfreqList );
2615- ifconf.ifc_req = pIfreqList;
2616- status = socket_ioctl ( *psocket, SIOCGIFCONF, &ifconf );
2617- if ( status < 0 || ifconf.ifc_len == 0 ) {
2618- char sockErrBuf[64];
2619- epicsSocketConvertErrnoToString (
2620- sockErrBuf, sizeof ( sockErrBuf ) );
2621- errlogPrintf (
2622- "osiLocalAddr(): SIOCGIFCONF ioctl failed because \"%s\"\n",
2623- sockErrBuf );
2624- goto fail;
2625- }
2626-
2627- pIfreqListEnd = (struct ifreq *) ( ifconf.ifc_len + (char *) ifconf.ifc_req );
2628- pIfreqListEnd--;
2629-
2630- for ( pifreq = ifconf.ifc_req; pifreq <= pIfreqListEnd; pifreq = pnextifreq ) {
2631- osiSockAddr addrCpy;
2632- uint32_t current_ifreqsize;
2633-
2634- /*
2635- * find the next if req
2636- */
2637- pnextifreq = ifreqNext ( pifreq );
2638-
2639- /* determine ifreq size */
2640- current_ifreqsize = ifreqSize ( pifreq );
2641- /* copy current ifreq to aligned bufferspace (to start of pIfreqList buffer) */
2642- memmove(pIfreqList, pifreq, current_ifreqsize);
2643-
2644- if ( pIfreqList->ifr_addr.sa_family != AF_INET ) {
2645- ifDepenDebugPrintf ( ("osiLocalAddr(): interface %s was not AF_INET\n", pIfreqList->ifr_name) );
2646- continue;
2647- }
2648-
2649- addrCpy.sa = pIfreqList->ifr_addr;
2650-
2651- status = socket_ioctl ( *psocket, SIOCGIFFLAGS, pIfreqList );
2652- if ( status < 0 ) {
2653- errlogPrintf ( "osiLocalAddr(): net intf flags fetch for %s failed\n", pIfreqList->ifr_name );
2654- continue;
2655- }
2656-
2657- if ( ! ( pIfreqList->ifr_flags & IFF_UP ) ) {
2658- ifDepenDebugPrintf ( ("osiLocalAddr(): net intf %s was down\n", pIfreqList->ifr_name) );
2659- continue;
2660- }
2661-
2662- /*
2663- * dont use the loop back interface
2664- */
2665- if ( pIfreqList->ifr_flags & IFF_LOOPBACK ) {
2666- ifDepenDebugPrintf ( ("osiLocalAddr(): ignoring loopback interface: %s\n", pIfreqList->ifr_name) );
2667- continue;
2668- }
2669-
2670- ifDepenDebugPrintf ( ("osiLocalAddr(): net intf %s found\n", pIfreqList->ifr_name) );
2671-
2672- osiLocalAddrResult = addrCpy;
2673- free ( pIfreqList );
2674- return;
2675- }
2676-
2677- errlogPrintf (
2678- "osiLocalAddr(): only loopback found\n");
2679-fail:
2680- /* fallback to loopback */
2681- memset ( (void *) &addr, '\0', sizeof ( addr ) );
2682- addr.ia.sin_family = AF_INET;
2683- addr.ia.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
2684- osiLocalAddrResult = addr;
2685-
2686- free ( pIfreqList );
2687-}
2688-
2689-
2690-epicsShareFunc osiSockAddr epicsShareAPI osiLocalAddr (SOCKET socket)
2691-{
2692- epicsThreadOnce(&osiLocalAddrId, osiLocalAddrOnce, &socket);
2693- return osiLocalAddrResult;
2694-}
2695+#ifdef USE_IFADDRS
2696+
2697+epicsShareFunc int osiGetInterfaceInfo(ELLLIST *pList, unsigned flags)
2698+{
2699+ int ret = -1;
2700+ struct ifaddrs *addrs = NULL, *cur;
2701+
2702+ ellFree(pList);
2703+
2704+ if(getifaddrs(&addrs))
2705+ goto cleanup;
2706+
2707+ for(cur=addrs; cur; cur=cur?cur->ifa_next:NULL)
2708+// for(cur=addrs; cur; cur=cur->ifa_next)
2709+ {
2710+ unsigned int flags;
2711+ osiInterfaceInfo *node = calloc(1, sizeof(*node));
2712+ if(!node)
2713+ goto cleanup;
2714+
2715+ switch(cur->ifa_addr->sa_family)
2716+ {
2717+ case AF_INET:
2718+ /*case AF_INET6:*/
2719+ break;
2720+ default:
2721+ free(node);
2722+ continue; /* ignore unknown address types */
2723+ }
2724+
2725+ //assert(cur->ifa_addr->sa_family==cur->ifa_netmask->sa_family);
2726+ memcpy(&node->address.ia, cur->ifa_addr, sizeof(node->address.ia));
2727+ memcpy(&node->netmask.ia, cur->ifa_netmask, sizeof(node->address.ia));
2728+
2729+ flags = cur->ifa_flags;
2730+
2731+ if(flags&IFF_UP) node->up = 1;
2732+ if(flags&IFF_BROADCAST) node->broadcast = 1;
2733+ if(flags&IFF_MULTICAST) node->multicast = 1;
2734+ if(flags&IFF_LOOPBACK) node->loopback = 1;
2735+ if(flags&IFF_POINTOPOINT) node->point2point = 1;
2736+
2737+ if(node->broadcast && node->point2point) {
2738+ errlogPrintf("Interface %s claims both broadcast and point to point,"
2739+ " which should not be possible. Assuming broadcast only.",
2740+ cur->ifa_name);
2741+ node->point2point = 0;
2742+ }
2743+
2744+ if(node->broadcast)
2745+ memcpy(&node->endpoint.ia, cur->ifa_broadaddr, sizeof(node->address.ia));
2746+ else if(node->point2point)
2747+ memcpy(&node->endpoint.ia, cur->ifa_dstaddr, sizeof(node->address.ia));
2748+
2749+ ellAdd(pList, &node->node);
2750+ }
2751+
2752+ ret = 0;
2753+cleanup:
2754+ if(ret)
2755+ ellFree(pList);
2756+ if(addrs) freeifaddrs(addrs);
2757+ return ret;
2758+}
2759+#else /* USE_IFADDRS */
2760+
2761+epicsShareFunc int osiGetInterfaceInfo(ELLLIST *pList, unsigned flags)
2762+{
2763+ SOCKET sock;
2764+ int ret = -1;
2765+ struct if_nameindex* pIndex = 0;
2766+ struct if_nameindex* pIndex2 = 0;
2767+
2768+ ellFree(pList);
2769+
2770+ sock = epicsSocketCreate(AF_INET, SOCK_DGRAM, 0);
2771+ if(sock==INVALID_SOCKET)
2772+ return ret;
2773+
2774+ pIndex = pIndex2 = if_nameindex();
2775+ while ((pIndex != NULL) && (pIndex->if_name != NULL))
2776+ {
2777+ struct ifreq req;
2778+ unsigned int flags;
2779+ osiInterfaceInfo *node = calloc(1, sizeof(*node));
2780+ if(!node)
2781+ goto cleanup;
2782+ strncpy(req.ifr_name, pIndex->if_name, IFNAMSIZ);
2783+ if(socket_ioctl(sock, SIOCGIFADDR, &req)<0) {
2784+ if (errno == EADDRNOTAVAIL) {
2785+ free(node);
2786+ ++pIndex;
2787+ continue;
2788+ }
2789+ free(node);
2790+ goto cleanup;
2791+ }
2792+ memcpy(&node->address.ia, &req.ifr_addr, sizeof(node->address.ia));
2793+
2794+ if(socket_ioctl(sock, SIOCGIFNETMASK, &req)<0) {
2795+ free(node);
2796+ goto cleanup;
2797+ }
2798+ memcpy(&node->netmask.ia, &req.ifr_addr, sizeof(node->netmask.ia));
2799+
2800+ if(socket_ioctl(sock, SIOCGIFFLAGS, &req)<0) {
2801+ free(node);
2802+ goto cleanup;
2803+ }
2804+ flags = req.ifr_flags;
2805+ if(flags&IFF_UP) node->up = 1;
2806+ if(flags&IFF_BROADCAST) node->broadcast = 1;
2807+ if(flags&IFF_MULTICAST) node->multicast = 1;
2808+ if(flags&IFF_LOOPBACK) node->loopback = 1;
2809+ if(flags&IFF_POINTOPOINT) node->point2point = 1;
2810+
2811+ if(node->broadcast && node->point2point) {
2812+ errlogPrintf("Interface %s claims both broadcast and point to point,"
2813+ " which should not be possible. Assuming broadcast only.",
2814+ req.ifr_name);
2815+ node->point2point = 0;
2816+ }
2817+ if(node->broadcast) {
2818+ if(socket_ioctl(sock, SIOCGIFBRDADDR, &req)<0) {
2819+ free(node);
2820+ goto cleanup;
2821+ }
2822+ } else if(node->point2point) {
2823+ if(socket_ioctl(sock, SIOCGIFDSTADDR, &req)<0) {
2824+ free(node);
2825+ goto cleanup;
2826+ }
2827+ }
2828+
2829+ if(node->broadcast || node->point2point) {
2830+ assert(req.ifr_addr.sa_family==node->address.sa.sa_family);
2831+
2832+ memcpy(&node->endpoint.ia, &req.ifr_addr, sizeof(node->endpoint.ia));
2833+ }
2834+
2835+ ellAdd(pList, &node->node);
2836+ ++pIndex;
2837+ }
2838+
2839+ ret = 0;
2840+cleanup:
2841+ if(ret)
2842+ ellFree(pList);
2843+ epicsSocketDestroy(sock);
2844+ return ret;
2845+}
2846+#endif /* USE_IFADRS */
2847
2848=== modified file 'src/libCom/osi/os/posix/osdSockAddrReuse.cpp'
2849--- src/libCom/osi/os/posix/osdSockAddrReuse.cpp 2016-05-22 12:38:18 +0000
2850+++ src/libCom/osi/os/posix/osdSockAddrReuse.cpp 2017-05-01 18:36:52 +0000
2851@@ -17,6 +17,12 @@
2852 #include "osiSock.h"
2853 #include "errlog.h"
2854
2855+#ifdef SO_REUSEPORT
2856+#define OPTION SO_REUSEPORT
2857+#else
2858+#define OPTION SO_REUSEADDR
2859+#endif
2860+
2861 epicsShareFunc void epicsShareAPI
2862 epicsSocketEnableAddressReuseDuringTimeWaitState ( SOCKET s )
2863 {
2864@@ -33,13 +39,14 @@
2865
2866 /*
2867 * SO_REUSEPORT is not in POSIX
2868+ * but in RTEMS
2869 */
2870 epicsShareFunc void epicsShareAPI
2871 epicsSocketEnableAddressUseForDatagramFanout ( SOCKET s )
2872 {
2873 int yes = true;
2874 int status;
2875- status = setsockopt ( s, SOL_SOCKET, SO_REUSEADDR,
2876+ status = setsockopt ( s, SOL_SOCKET, OPTION,
2877 (char *) & yes, sizeof ( yes ) );
2878 if ( status < 0 ) {
2879 errlogPrintf (
2880
2881=== modified file 'src/libCom/osi/os/posix/osdThread.c'
2882--- src/libCom/osi/os/posix/osdThread.c 2016-02-23 21:43:26 +0000
2883+++ src/libCom/osi/os/posix/osdThread.c 2017-05-01 18:36:52 +0000
2884@@ -4,11 +4,19 @@
2885 * Copyright (c) 2002 The Regents of the University of California, as
2886 * Operator of Los Alamos National Laboratory.
2887 * Copyright (c) 2013 ITER Organization.
2888+* Copyright (c) 2017 Fritz-Haber-Institut der Max-Planck-Gesellschaft
2889 * EPICS BASE is distributed subject to a Software License Agreement found
2890 * in file LICENSE that is included with this distribution.
2891 \*************************************************************************/
2892
2893-/* Author: Marty Kraimer Date: 18JAN2000 */
2894+/* Author: Marty Kraimer Date: 18JAN2000
2895+ Heinz Junkes Date: 06APR2017
2896+
2897+ once() and all called functions by once must use
2898+ checkStatusOnce and checkStatusQuitOnce only
2899+ including epicsEventCreate called by create_threadInfo
2900+ add epicsEventCreateOnce which can be called here
2901+*/
2902
2903 /* This is a posix implementation of epicsThread */
2904 #include <stddef.h>
2905@@ -38,6 +46,16 @@
2906 #include "errlog.h"
2907 #include "epicsAssert.h"
2908 #include "epicsExit.h"
2909+#if defined(__rtems__)
2910+#include <rtems/bspIo.h>
2911+#include <rtems.h>
2912+#endif
2913+
2914+struct epicsEventOSD {
2915+ pthread_mutex_t mutex;
2916+ pthread_cond_t cond;
2917+ int isFull;
2918+};
2919
2920 epicsShareFunc void epicsThreadShowInfo(epicsThreadOSD *pthreadInfo, unsigned int level);
2921 epicsShareFunc void osdThreadHooksRun(epicsThreadId id);
2922@@ -75,14 +93,15 @@
2923 } priAvailable;
2924 #endif
2925
2926-static pthread_key_t getpthreadInfo;
2927+__thread epicsThreadOSD *tls_pthreadInfo;
2928+
2929 static pthread_mutex_t onceLock;
2930 static pthread_mutex_t listLock;
2931 static ELLLIST pthreadList = ELLLIST_INIT;
2932 static commonAttr *pcommonAttr = 0;
2933-static int epicsThreadOnceCalled = 0;
2934+static int epicsThreadInitOnceCalled = 0;
2935
2936
2937-static epicsThreadOSD *createImplicit(void);
2938+static void createImplicit(void);
2939
2940 #define checkStatus(status,message) \
2941 if((status)) {\
2942@@ -90,7 +109,7 @@
2943 }
2944
2945 #define checkStatusQuit(status,message,method) \
2946-if(status) { \
2947+if((status)) { \
2948 errlogPrintf("%s error %s\n",(message),strerror((status))); \
2949 cantProceed((method)); \
2950 }
2951@@ -99,17 +118,33 @@
2952 /* Until epicsThreadInit completes errlogInit will not work */
2953 /* It must also be used by init_threadInfo otherwise errlogInit could get */
2954 /* called recursively */
2955+#if defined (__rtems__)
2956+#define checkStatusOnce(status,message) \
2957+if((status)) {\
2958+ printk("%s error %s\n",(message),strerror((status))); }
2959+#else
2960 #define checkStatusOnce(status,message) \
2961 if((status)) {\
2962 fprintf(stderr,"%s error %s\n",(message),strerror((status))); }
2963+#endif
2964
2965-#define checkStatusOnceQuit(status,message,method) \
2966-if(status) { \
2967+#if defined (__rtems__)
2968+#define checkStatusOnceQuit(status,message,method) \
2969+if((status)) { \
2970+ printk("%s error %s",(message),strerror((status))); \
2971+ printk(" %s\n",method); \
2972+ printk("epicsThreadInit cant proceed. Program exiting\n"); \
2973+ exit(-1);\
2974+}
2975+#else
2976+#define checkStatusOnceQuit(status,message,method) \
2977+if((status)) { \
2978 fprintf(stderr,"%s error %s",(message),strerror((status))); \
2979 fprintf(stderr," %s\n",method); \
2980 fprintf(stderr,"epicsThreadInit cant proceed. Program exiting\n"); \
2981 exit(-1);\
2982 }
2983+#endif
2984
2985
2986
2987 epicsShareFunc int epicsThreadGetPosixPriority(epicsThreadId pthreadInfo)
2988@@ -153,6 +188,29 @@
2989 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
2990 }
2991
2992
2993+
2994+epicsShareFunc epicsEventId epicsEventCreateOnce(epicsEventInitialState init)
2995+{
2996+ epicsEventId pevent = malloc(sizeof(*pevent));
2997+ if (pevent) {
2998+ int status = pthread_mutex_init(&pevent->mutex, 0);
2999+
3000+ pevent->isFull = (init == epicsEventFull);
3001+ if (status) {
3002+ checkStatus(status, "pthread_mutex_init");
3003+ } else {
3004+ status = pthread_cond_init(&pevent->cond, 0);
3005+ if (!status)
3006+ return pevent;
3007+ checkStatus(status, "pthread_cond_init");
3008+ status = pthread_mutex_destroy(&pevent->mutex);
3009+ checkStatus(status, "pthread_mutex_destroy");
3010+ }
3011+ free(pevent);
3012+ }
3013+ return NULL;
3014+}
3015+
3016 static epicsThreadOSD * create_threadInfo(const char *name)
3017 {
3018 epicsThreadOSD *pthreadInfo;
3019@@ -161,7 +219,7 @@
3020 pthreadInfo = calloc(1,sizeof(*pthreadInfo) + strlen(name));
3021 if(!pthreadInfo)
3022 return NULL;
3023- pthreadInfo->suspendEvent = epicsEventCreate(epicsEventEmpty);
3024+ pthreadInfo->suspendEvent = epicsEventCreateOnce(epicsEventEmpty);
3025 if(!pthreadInfo->suspendEvent){
3026 free(pthreadInfo);
3027 return NULL;
3028@@ -204,11 +262,13 @@
3029 {
3030 int status;
3031
3032- status = mutexLock(&listLock);
3033- checkStatusQuit(status,"pthread_mutex_lock","free_threadInfo");
3034- if(pthreadInfo->isOnThreadList) ellDelete(&pthreadList,&pthreadInfo->node);
3035- status = pthread_mutex_unlock(&listLock);
3036- checkStatusQuit(status,"pthread_mutex_unlock","free_threadInfo");
3037+ if(pthreadInfo->isOnThreadList) {
3038+ status = mutexLock(&listLock);
3039+ checkStatusQuit(status,"pthread_mutex_lock","free_threadInfo");
3040+ ellDelete(&pthreadList,&pthreadInfo->node);
3041+ status = pthread_mutex_unlock(&listLock);
3042+ checkStatusQuit(status,"pthread_mutex_unlock","free_threadInfo");
3043+ }
3044 epicsEventDestroy(pthreadInfo->suspendEvent);
3045 status = pthread_attr_destroy(&pthreadInfo->attr);
3046 checkStatusQuit(status,"pthread_attr_destroy","free_threadInfo");
3047@@ -301,13 +361,19 @@
3048 arg.ok = 0;
3049
3050 status = pthread_create(&id, 0, find_pri_range, &arg);
3051- checkStatusQuit(status, "pthread_create","epicsThreadInit");
3052+ checkStatusOnceQuit(status, "pthread_create","findPriorityRange");
3053
3054 status = pthread_join(id, &dummy);
3055- checkStatusQuit(status, "pthread_join","epicsThreadInit");
3056-
3057+ checkStatusOnceQuit(status, "pthread_join","findPriorityRange");
3058+#if defined (__rtems__)
3059+// We are using posix map osi 0-100 to posix 100-200
3060+// see epicsThreadGetOsiPriorityValue(int ossPriority)
3061+ a_p->minPriority = 100;
3062+ a_p->maxPriority = 200;
3063+#else
3064 a_p->minPriority = arg.min_pri;
3065 a_p->maxPriority = arg.max_pri;
3066+#endif
3067 a_p->usePolicy = arg.ok;
3068 }
3069 #endif
3070@@ -315,18 +381,15 @@
3071
3072 static void once(void)
3073 {
3074- epicsThreadOSD *pthreadInfo;
3075 int status;
3076-
3077- pthread_key_create(&getpthreadInfo,0);
3078 status = pthread_mutex_init(&onceLock,0);
3079- checkStatusQuit(status,"pthread_mutex_init","epicsThreadInit");
3080+ checkStatusOnceQuit(status,"pthread_mutex_init","once");
3081 status = pthread_mutex_init(&listLock,0);
3082- checkStatusQuit(status,"pthread_mutex_init","epicsThreadInit");
3083+ checkStatusOnceQuit(status,"pthread_mutex_init","once");
3084 pcommonAttr = calloc(1,sizeof(commonAttr));
3085- if(!pcommonAttr) checkStatusOnceQuit(errno,"calloc","epicsThreadInit");
3086+ if(!pcommonAttr) checkStatusOnceQuit(errno,"calloc","once");
3087 status = pthread_attr_init(&pcommonAttr->attr);
3088- checkStatusOnceQuit(status,"pthread_attr_init","epicsThreadInit");
3089+ checkStatusOnceQuit(status,"pthread_attr_init","once");
3090 status = pthread_attr_setdetachstate(
3091 &pcommonAttr->attr, PTHREAD_CREATE_DETACHED);
3092 checkStatusOnce(status,"pthread_attr_setdetachstate");
3093@@ -358,52 +421,77 @@
3094 }
3095
3096 if (errVerbose) {
3097+#if defined(__rtems__)
3098+ printk("LRT: min priority: %d max priority %d\n",
3099+ pcommonAttr->minPriority, pcommonAttr->maxPriority);
3100+#else
3101 fprintf(stderr, "LRT: min priority: %d max priority %d\n",
3102 pcommonAttr->minPriority, pcommonAttr->maxPriority);
3103+#endif
3104 }
3105
3106 #else
3107- if(errVerbose) fprintf(stderr,"task priorities are not implemented\n");
3108+ if(errVerbose) {
3109+#if defined(__rtems__)
3110+ printk("task priorities are not implemented\n");
3111+#else
3112+ fprintf(stderr,"task priorities are not implemented\n");
3113+#endif
3114+}
3115 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
3116+ int policy;
3117+ struct sched_param param;
3118+ status = pthread_getschedparam(pthread_self(), &policy, &param);
3119+ checkStatusOnce(status, "pthread_getschedparam failed");
3120+// param.sched_priority is still 2 bug or feature?
3121+#if defined (__rtems__)
3122+ param.sched_priority = 191; // iocsh prio
3123+#endif
3124+ status = pthread_setschedparam(pthread_self(), policy, &param);
3125+ checkStatusOnce(status, "pthread_setschedparam failed");
3126+ status = pthread_getschedparam(pthread_self(), &policy, &param);
3127+ checkStatusOnce(status, "pthread_getschedparam failed");
3128
3129- pthreadInfo = init_threadInfo("_main_",0,epicsThreadGetStackSize(epicsThreadStackSmall),0,0);
3130- assert(pthreadInfo!=NULL);
3131- status = pthread_setspecific(getpthreadInfo,(void *)pthreadInfo);
3132- checkStatusOnceQuit(status,"pthread_setspecific","epicsThreadInit");
3133+#if defined (__rtems__)
3134+ tls_pthreadInfo = init_threadInfo("_main_",param.sched_priority-100,epicsThreadGetStackSize(epicsThreadStackSmall),0,0);
3135+#else
3136+ tls_pthreadInfo = init_threadInfo("_main_",0,epicsThreadGetStackSize(epicsThreadStackSmall),0,0);
3137+#endif
3138+ assert(tls_pthreadInfo!=NULL);
3139+ tls_pthreadInfo->tid = pthread_self();
3140 status = mutexLock(&listLock);
3141- checkStatusQuit(status,"pthread_mutex_lock","epicsThreadInit");
3142- ellAdd(&pthreadList,&pthreadInfo->node);
3143- pthreadInfo->isOnThreadList = 1;
3144+ checkStatusOnceQuit(status,"pthread_mutex_lock","once");
3145+ ellAdd(&pthreadList,&tls_pthreadInfo->node);
3146+ tls_pthreadInfo->isOnThreadList = 1;
3147 status = pthread_mutex_unlock(&listLock);
3148- checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadInit");
3149+ checkStatusOnceQuit(status,"pthread_mutex_unlock","once");
3150 status = atexit(epicsExitCallAtExits);
3151 checkStatusOnce(status,"atexit");
3152- osdThreadHooksRunMain(pthreadInfo);
3153- epicsThreadOnceCalled = 1;
3154+ osdThreadHooksRunMain(tls_pthreadInfo);
3155+ epicsThreadInitOnceCalled = 1;
3156 }
3157
3158 static void * start_routine(void *arg)
3159 {
3160- epicsThreadOSD *pthreadInfo = (epicsThreadOSD *)arg;
3161 int status;
3162 sigset_t blockAllSig;
3163
3164+ tls_pthreadInfo = (epicsThreadOSD *)arg;
3165+
3166 sigfillset(&blockAllSig);
3167 pthread_sigmask(SIG_SETMASK,&blockAllSig,NULL);
3168- status = pthread_setspecific(getpthreadInfo,arg);
3169- checkStatusQuit(status,"pthread_setspecific","start_routine");
3170 status = mutexLock(&listLock);
3171 checkStatusQuit(status,"pthread_mutex_lock","start_routine");
3172- ellAdd(&pthreadList,&pthreadInfo->node);
3173- pthreadInfo->isOnThreadList = 1;
3174+ ellAdd(&pthreadList,&tls_pthreadInfo->node);
3175+ tls_pthreadInfo->isOnThreadList = 1;
3176 status = pthread_mutex_unlock(&listLock);
3177 checkStatusQuit(status,"pthread_mutex_unlock","start_routine");
3178- osdThreadHooksRun(pthreadInfo);
3179+ osdThreadHooksRun(tls_pthreadInfo);
3180
3181- (*pthreadInfo->createFunc)(pthreadInfo->createArg);
3182+ (*tls_pthreadInfo->createFunc)(tls_pthreadInfo->createArg);
3183
3184 epicsExitCallAtThreadExits ();
3185- free_threadInfo(pthreadInfo);
3186+ free_threadInfo(tls_pthreadInfo);
3187 return(0);
3188 }
3189
3190@@ -417,6 +505,9 @@
3191 epicsShareFunc
3192 void epicsThreadRealtimeLock(void)
3193 {
3194+#if !defined(__rtems__)
3195+/* RTEMS defines _POSIX_MEMLOCK to 1 in features.h even if it is a non swaping OS and
3196+ mlockall senseless*/
3197 #if defined(_POSIX_MEMLOCK) && _POSIX_MEMLOCK > 0
3198 if (pcommonAttr->maxPriority > pcommonAttr->minPriority) {
3199 int status = mlockall(MCL_CURRENT | MCL_FUTURE);
3200@@ -424,10 +515,11 @@
3201 if (status) {
3202 fprintf(stderr, "epicsThreadRealtimeLock "
3203 "Warning: Unable to lock the virtual address space.\n"
3204- "VM page faults may harm real-time performance.\n");
3205+ "VM page fautls may harm real-time performance.\n");
3206 }
3207 }
3208 #endif
3209+#endif /* not defined __rtems__ */
3210 }
3211
3212 epicsShareFunc unsigned int epicsShareAPI epicsThreadGetStackSize (epicsThreadStackSizeClass stackSizeClass)
3213@@ -435,7 +527,11 @@
3214 #if defined (OSITHREAD_USE_DEFAULT_STACK)
3215 return 0;
3216 #elif defined(_POSIX_THREAD_ATTR_STACKSIZE) && _POSIX_THREAD_ATTR_STACKSIZE > 0
3217+#if defined (__rtems)
3218+ #define STACK_SIZE(f) (f * 0x1000 * sizeof(void *))
3219+#else
3220 #define STACK_SIZE(f) (f * 0x10000 * sizeof(void *))
3221+#endif
3222 static const unsigned stackSizeTable[epicsThreadStackBig+1] = {
3223 STACK_SIZE(1), STACK_SIZE(2), STACK_SIZE(4)
3224 };
3225@@ -463,37 +559,33 @@
3226
3227 epicsThreadInit();
3228 status = mutexLock(&onceLock);
3229- if(status) {
3230- fprintf(stderr,"epicsThreadOnce: pthread_mutex_lock returned %s.\n",
3231- strerror(status));
3232- exit(-1);
3233- }
3234+ checkStatusOnceQuit(status,"pthread_mutex_lock", "epicsThreadOnce");
3235
3236 if (*id != EPICS_THREAD_ONCE_DONE) {
3237 if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */
3238 *id = epicsThreadGetIdSelf(); /* mark active */
3239 status = pthread_mutex_unlock(&onceLock);
3240- checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
3241+ checkStatusOnceQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
3242 func(arg);
3243 status = mutexLock(&onceLock);
3244- checkStatusQuit(status,"pthread_mutex_lock", "epicsThreadOnce");
3245+ checkStatusOnceQuit(status,"pthread_mutex_lock", "epicsThreadOnce");
3246 *id = EPICS_THREAD_ONCE_DONE; /* mark done */
3247 } else if (*id == epicsThreadGetIdSelf()) {
3248 status = pthread_mutex_unlock(&onceLock);
3249- checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
3250+ checkStatusOnceQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
3251 cantProceed("Recursive epicsThreadOnce() initialization\n");
3252 } else
3253 while (*id != EPICS_THREAD_ONCE_DONE) {
3254 /* Another thread is in the above func(arg) call. */
3255 status = pthread_mutex_unlock(&onceLock);
3256- checkStatusQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
3257+ checkStatusOnceQuit(status,"pthread_mutex_unlock", "epicsThreadOnce");
3258 epicsThreadSleep(epicsThreadSleepQuantum());
3259 status = mutexLock(&onceLock);
3260- checkStatusQuit(status,"pthread_mutex_lock", "epicsThreadOnce");
3261+ checkStatusOnceQuit(status,"pthread_mutex_lock", "epicsThreadOnce");
3262 }
3263 }
3264 status = pthread_mutex_unlock(&onceLock);
3265- checkStatusQuit(status,"pthread_mutex_unlock","epicsThreadOnce");
3266+ checkStatusOnceQuit(status,"pthread_mutex_unlock","epicsThreadOnce");
3267 }
3268
3269 epicsShareFunc epicsThreadId epicsShareAPI epicsThreadCreate(const char *name,
3270@@ -530,6 +622,7 @@
3271 return 0;
3272 }
3273 status = pthread_sigmask(SIG_SETMASK,&oldSig,NULL);
3274+//? StatusOnce? because of errlog daemon ???
3275 checkStatusOnce(status,"pthread_sigmask");
3276 return(pthreadInfo);
3277 }
3278@@ -537,80 +630,64 @@
3279 /*
3280 * Create dummy context for threads not created by epicsThreadCreate().
3281 */
3282-static epicsThreadOSD *createImplicit(void)
3283+static void createImplicit(void)
3284 {
3285- epicsThreadOSD *pthreadInfo;
3286 char name[64];
3287 pthread_t tid;
3288- int status;
3289
3290 tid = pthread_self();
3291 sprintf(name, "non-EPICS_%ld", (long)tid);
3292- pthreadInfo = create_threadInfo(name);
3293- assert(pthreadInfo);
3294- pthreadInfo->tid = tid;
3295- pthreadInfo->osiPriority = 0;
3296+ tls_pthreadInfo = create_threadInfo(name);
3297+ assert(tls_pthreadInfo);
3298+ tls_pthreadInfo->tid = tid;
3299+ tls_pthreadInfo->osiPriority = 0;
3300
3301 #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0
3302 {
3303 struct sched_param param;
3304 int policy;
3305 if(pthread_getschedparam(tid,&policy,&param) == 0)
3306- pthreadInfo->osiPriority =
3307+ tls_pthreadInfo->osiPriority =
3308 (param.sched_priority - pcommonAttr->minPriority) * 100.0 /
3309- (pcommonAttr->maxPriority - pcommonAttr->minPriority + 1);
3310+ (pcommonAttr->maxPriority - pcommonAttr->minPriority);
3311 }
3312 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
3313-
3314- status = pthread_setspecific(getpthreadInfo,(void *)pthreadInfo);
3315- checkStatus(status,"pthread_setspecific createImplicit");
3316- if(status){
3317- free_threadInfo(pthreadInfo);
3318- return NULL;
3319- }
3320- return pthreadInfo;
3321 }
3322
3323
3324 epicsShareFunc void epicsShareAPI epicsThreadSuspendSelf(void)
3325 {
3326- epicsThreadOSD *pthreadInfo;
3327-
3328 epicsThreadInit();
3329- pthreadInfo = (epicsThreadOSD *)pthread_getspecific(getpthreadInfo);
3330- if(pthreadInfo==NULL)
3331- pthreadInfo = createImplicit();
3332- pthreadInfo->isSuspended = 1;
3333- epicsEventWait(pthreadInfo->suspendEvent);
3334+ assert(tls_pthreadInfo);
3335+ tls_pthreadInfo->isSuspended = 1;
3336+ epicsEventWait(tls_pthreadInfo->suspendEvent);
3337 }
3338
3339 epicsShareFunc void epicsShareAPI epicsThreadResume(epicsThreadOSD *pthreadInfo)
3340 {
3341- assert(epicsThreadOnceCalled);
3342+ assert(epicsThreadInitOnceCalled);
3343 pthreadInfo->isSuspended = 0;
3344 epicsEventSignal(pthreadInfo->suspendEvent);
3345 }
3346
3347 epicsShareFunc void epicsShareAPI epicsThreadExitMain(void)
3348 {
3349- epicsThreadOSD *pthreadInfo;
3350
3351 epicsThreadInit();
3352- pthreadInfo = (epicsThreadOSD *)pthread_getspecific(getpthreadInfo);
3353- if(pthreadInfo==NULL)
3354- pthreadInfo = createImplicit();
3355- if(pthreadInfo->createFunc) {
3356+ if(tls_pthreadInfo==NULL)
3357+ createImplicit();
3358+ if(tls_pthreadInfo->createFunc) {
3359 errlogPrintf("called from non-main thread\n");
3360 cantProceed("epicsThreadExitMain");
3361 }
3362 else {
3363- free_threadInfo(pthreadInfo);
3364+ free_threadInfo(tls_pthreadInfo);
3365 pthread_exit(0);
3366 }
3367 }
3368
3369
3370 epicsShareFunc unsigned int epicsShareAPI epicsThreadGetPriority(epicsThreadId pthreadInfo)
3371 {
3372- assert(epicsThreadOnceCalled);
3373+ assert(epicsThreadInitOnceCalled);
3374 return(pthreadInfo->osiPriority);
3375 }
3376
3377@@ -626,7 +703,7 @@
3378 int status;
3379 #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
3380
3381- assert(epicsThreadOnceCalled);
3382+ assert(epicsThreadInitOnceCalled);
3383 assert(pthreadInfo);
3384 if(!pthreadInfo->isEpicsThread) {
3385 fprintf(stderr,"epicsThreadSetPriority called by non epics thread\n");
3386@@ -637,7 +714,7 @@
3387
3388 #if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0
3389 if(!pcommonAttr->usePolicy) return;
3390- pthreadInfo->schedParam.sched_priority = epicsThreadGetPosixPriority(pthreadInfo);
3391+ tls_pthreadInfo->schedParam.sched_priority = epicsThreadGetPosixPriority(pthreadInfo);
3392 status = pthread_attr_setschedparam(
3393 &pthreadInfo->attr,&pthreadInfo->schedParam);
3394 if(errVerbose) checkStatus(status,"pthread_attr_setschedparam");
3395@@ -685,14 +762,14 @@
3396
3397
3398 epicsShareFunc int epicsShareAPI epicsThreadIsEqual(epicsThreadId p1, epicsThreadId p2)
3399 {
3400- assert(epicsThreadOnceCalled);
3401+ assert(epicsThreadInitOnceCalled);
3402 assert(p1);
3403 assert(p2);
3404 return(pthread_equal(p1->tid,p2->tid));
3405 }
3406
3407 epicsShareFunc int epicsShareAPI epicsThreadIsSuspended(epicsThreadId pthreadInfo) {
3408- assert(epicsThreadOnceCalled);
3409+ assert(epicsThreadInitOnceCalled);
3410 assert(pthreadInfo);
3411 return(pthreadInfo->isSuspended ? 1 : 0);
3412 }
3413@@ -718,14 +795,11 @@
3414 }
3415
3416 epicsShareFunc epicsThreadId epicsShareAPI epicsThreadGetIdSelf(void) {
3417- epicsThreadOSD *pthreadInfo;
3418
3419 epicsThreadInit();
3420- pthreadInfo = (epicsThreadOSD *)pthread_getspecific(getpthreadInfo);
3421- if(pthreadInfo==NULL)
3422- pthreadInfo = createImplicit();
3423- assert ( pthreadInfo );
3424- return(pthreadInfo);
3425+ if(tls_pthreadInfo==NULL)
3426+ createImplicit();
3427+ return(tls_pthreadInfo);
3428 }
3429
3430 epicsShareFunc pthread_t epicsThreadGetPosixThreadId ( epicsThreadId threadId )
3431@@ -737,7 +811,7 @@
3432 epicsThreadOSD *pthreadInfo;
3433 int status;
3434
3435- assert(epicsThreadOnceCalled);
3436+ assert(epicsThreadInitOnceCalled);
3437 status = mutexLock(&listLock);
3438 checkStatus(status,"pthread_mutex_lock epicsThreadGetId");
3439 if(status)
3440@@ -755,18 +829,16 @@
3441
3442 epicsShareFunc const char epicsShareAPI *epicsThreadGetNameSelf()
3443 {
3444- epicsThreadOSD *pthreadInfo;
3445
3446 epicsThreadInit();
3447- pthreadInfo = (epicsThreadOSD *)pthread_getspecific(getpthreadInfo);
3448- if(pthreadInfo==NULL)
3449- pthreadInfo = createImplicit();
3450- return(pthreadInfo->name);
3451+ if(tls_pthreadInfo==NULL)
3452+ createImplicit();
3453+ return(tls_pthreadInfo->name);
3454 }
3455
3456 epicsShareFunc void epicsShareAPI epicsThreadGetName(epicsThreadId pthreadInfo, char *name, size_t size)
3457 {
3458- assert(epicsThreadOnceCalled);
3459+ assert(epicsThreadInitOnceCalled);
3460 strncpy(name, pthreadInfo->name, size-1);
3461 name[size-1] = '\0';
3462 }
3463@@ -822,7 +894,7 @@
3464 return;
3465 }
3466 status = mutexLock(&listLock);
3467- checkStatus(status,"pthread_mutex_lock epicsThreadShowAll");
3468+ checkStatus(status,"pthread_mutex_lock epicsThreadShow");
3469 if(status)
3470 return;
3471 pthreadInfo=(epicsThreadOSD *)ellFirst(&pthreadList);
3472@@ -835,7 +907,7 @@
3473 pthreadInfo=(epicsThreadOSD *)ellNext(&pthreadInfo->node);
3474 }
3475 status = pthread_mutex_unlock(&listLock);
3476- checkStatus(status,"pthread_mutex_unlock epicsThreadShowAll");
3477+ checkStatus(status,"pthread_mutex_unlock epicsThreadShow");
3478 if(status) return;
3479 if (!found)
3480 printf("Thread %#lx (%lu) not found.\n", (unsigned long)showThread, (unsigned long)showThread);
3481@@ -851,7 +923,8 @@
3482 if(!key)
3483 return NULL;
3484 status = pthread_key_create(key,0);
3485- checkStatus(status,"pthread_key_create epicsThreadPrivateCreate");
3486+//used from errlogInit
3487+ checkStatusOnce(status,"pthread_key_create epicsThreadPrivateCreate");
3488 if(status)
3489 return NULL;
3490 return((epicsThreadPrivateId)key);
3491@@ -862,7 +935,7 @@
3492 pthread_key_t *key = (pthread_key_t *)id;
3493 int status;
3494
3495- assert(epicsThreadOnceCalled);
3496+ assert(epicsThreadInitOnceCalled);
3497 status = pthread_key_delete(*key);
3498 checkStatusQuit(status,"pthread_key_delete","epicsThreadPrivateDelete");
3499 free((void *)key);
3500@@ -873,7 +946,7 @@
3501 pthread_key_t *key = (pthread_key_t *)id;
3502 int status;
3503
3504- assert(epicsThreadOnceCalled);
3505+ assert(epicsThreadInitOnceCalled);
3506 if(errVerbose && !value)
3507 errlogPrintf("epicsThreadPrivateSet: setting value of 0\n");
3508 status = pthread_setspecific(*key,value);
3509@@ -884,7 +957,7 @@
3510 {
3511 pthread_key_t *key = (pthread_key_t *)id;
3512
3513- assert(epicsThreadOnceCalled);
3514+ assert(epicsThreadInitOnceCalled);
3515 return pthread_getspecific(*key);
3516 }
3517
3518
3519=== modified file 'src/libCom/osi/os/posix/osdThreadExtra.c'
3520--- src/libCom/osi/os/posix/osdThreadExtra.c 2013-03-27 09:56:34 +0000
3521+++ src/libCom/osi/os/posix/osdThreadExtra.c 2017-05-01 18:36:52 +0000
3522@@ -24,22 +24,26 @@
3523 {
3524 if(!pthreadInfo) {
3525 fprintf(epicsGetStdout()," NAME EPICS ID "
3526- "PTHREAD ID OSIPRI OSSPRI STATE\n");
3527+ "PTHREAD ID OSIPRI OSSPRI STATE STACKSIZE\n");
3528 } else {
3529 struct sched_param param;
3530 int policy;
3531 int priority = 0;
3532+ size_t stackSize = 0;
3533
3534 if(pthreadInfo->tid) {
3535 int status;
3536 status = pthread_getschedparam(pthreadInfo->tid,&policy,&param);
3537 if(!status) priority = param.sched_priority;
3538+ status = pthread_attr_getstacksize( &pthreadInfo->attr,&stackSize);
3539+ if(status) stackSize = 0;
3540 }
3541- fprintf(epicsGetStdout(),"%16.16s %14p %12lu %3d%8d %8.8s\n",
3542+ fprintf(epicsGetStdout(),"%16.16s %14p 0x%08X %3d%8d %8.8s %9d\n",
3543 pthreadInfo->name,(void *)
3544 pthreadInfo,(unsigned long)pthreadInfo->tid,
3545 pthreadInfo->osiPriority,priority,
3546- pthreadInfo->isSuspended?"SUSPEND":"OK");
3547+ pthreadInfo->isSuspended?"SUSPEND":"OK",
3548+ stackSize);
3549 }
3550 }
3551
3552
3553=== modified file 'src/libCom/osi/osiSock.c'
3554--- src/libCom/osi/osiSock.c 2016-05-22 03:43:09 +0000
3555+++ src/libCom/osi/osiSock.c 2017-05-01 18:36:52 +0000
3556@@ -3,6 +3,8 @@
3557 * National Laboratory.
3558 * Copyright (c) 2002 The Regents of the University of California, as
3559 * Operator of Los Alamos National Laboratory.
3560+* Copyright (c) 2015 Brookhaven Science Associates as Operator of
3561+* Brookhaven National Lab.
3562 * EPICS BASE Versions 3.13.7
3563 * and higher are distributed subject to a Software License Agreement found
3564 * in file LICENSE that is included with this distribution.
3565@@ -15,12 +17,15 @@
3566 */
3567
3568 #include <stdio.h>
3569+#include <stdlib.h>
3570 #include <string.h>
3571
3572 #define epicsExportSharedSymbols
3573 #include "epicsAssert.h"
3574 #include "epicsSignal.h"
3575 #include "epicsStdio.h"
3576+#include "dbDefs.h"
3577+#include "errlog.h"
3578 #include "osiSock.h"
3579
3580 #define nDigitsDottedIP 4u
3581@@ -187,3 +192,155 @@
3582 }
3583 }
3584
3585+epicsShareFunc void osiFreeInterfaceInfo(osiInterfaceInfo *pinfo)
3586+{
3587+ free(pinfo);
3588+}
3589+
3590+/*
3591+ * osiSockDiscoverBroadcastAddresses ()
3592+ */
3593+epicsShareFunc void epicsShareAPI osiSockDiscoverBroadcastAddresses
3594+ (ELLLIST *pList, SOCKET socket, const osiSockAddr *pMatchAddr)
3595+{
3596+ ELLLIST infolist = ELLLIST_INIT;
3597+ ELLNODE *cur;
3598+
3599+ if ( pMatchAddr->sa.sa_family == AF_INET ) {
3600+ if ( pMatchAddr->ia.sin_addr.s_addr == htonl (INADDR_LOOPBACK) ) {
3601+ osiSockAddrNode *pNewNode = calloc (1, sizeof (*pNewNode) );
3602+ if ( pNewNode == NULL ) {
3603+ errlogPrintf ( "osiSockDiscoverBroadcastAddresses(): no memory available for configuration\n" );
3604+ return;
3605+ }
3606+ pNewNode->addr.ia.sin_family = AF_INET;
3607+ pNewNode->addr.ia.sin_port = htons ( 0 );
3608+ pNewNode->addr.ia.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
3609+ ellAdd ( pList, &pNewNode->node );
3610+ return;
3611+ }
3612+ } else if ( pMatchAddr->sa.sa_family != AF_UNSPEC ) {
3613+ errlogPrintf("osiSockDiscoverBroadcastAddresses(): match address must be AF_INET or AF_UNSPEC.");
3614+ return;
3615+ }
3616+
3617+ if(osiGetInterfaceInfo(&infolist, 0)) {
3618+ errlogPrintf ("osiSockDiscoverBroadcastAddresses(): unable to fetch network interface configuration\n");
3619+ return;
3620+ }
3621+
3622+ if(ellCount(&infolist)==0) {
3623+ errlogPrintf ("osiSockDiscoverBroadcastAddresses(): no network interfaces found\n");
3624+ }
3625+
3626+ for(cur=ellFirst(&infolist); cur; cur=ellNext(cur))
3627+ {
3628+ osiSockAddrNode *pNewNode;
3629+ osiInterfaceInfo *info = CONTAINER(cur, osiInterfaceInfo, node);
3630+
3631+ if(info->address.sa.sa_family!=AF_INET || !info->broadcast)
3632+ continue;
3633+
3634+ pNewNode = calloc(1, sizeof(*pNewNode));
3635+ if(!pNewNode)
3636+ break;
3637+
3638+ if(pMatchAddr->ia.sin_family==AF_INET &&
3639+ pMatchAddr->ia.sin_addr.s_addr != htonl(INADDR_ANY) &&
3640+ pMatchAddr->ia.sin_addr.s_addr != info->address.ia.sin_addr.s_addr)
3641+ {
3642+ free(pNewNode);
3643+ continue;
3644+ }
3645+
3646+ pNewNode->addr.ia = info->endpoint.ia;
3647+
3648+ ellAdd(pList, &pNewNode->node);
3649+ }
3650+
3651+ ellFree2(&infolist, (FREEFUNC)osiFreeInterfaceInfo);
3652+}
3653+
3654+/*
3655+ * osiLocalAddr ()
3656+ */
3657+epicsShareFunc osiSockAddr epicsShareAPI osiLocalAddr (SOCKET socket)
3658+{
3659+ static osiSockAddr result;
3660+ static int init;
3661+
3662+ if(!init) {
3663+ ELLLIST infolist = ELLLIST_INIT;
3664+ ELLNODE *cur;
3665+ osiSockAddr addr;
3666+ int found = 0;
3667+
3668+ memset ( (void *) &addr, '\0', sizeof ( addr ) );
3669+ addr.sa.sa_family = AF_UNSPEC;
3670+
3671+ if(osiGetInterfaceInfo(&infolist, 0)) {
3672+ errlogPrintf ("osiLocalAddr(): unable to fetch network interface configuration\n");
3673+
3674+ } else {
3675+
3676+ for(cur=ellFirst(&infolist); cur; cur=ellNext(cur))
3677+ {
3678+ osiInterfaceInfo *info = CONTAINER(cur, osiInterfaceInfo, node);
3679+
3680+ if(info->address.sa.sa_family!=AF_INET || !info->up || info->loopback)
3681+ continue;
3682+
3683+ addr.ia = info->address.ia;
3684+ found = 1;
3685+ }
3686+
3687+ ellFree(&infolist);
3688+ }
3689+
3690+ if(!found) {
3691+ addr.ia.sin_family = AF_INET;
3692+ addr.ia.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
3693+ addr.ia.sin_port = 0;
3694+ }
3695+
3696+ result = addr;
3697+ init = 1;
3698+ }
3699+
3700+ return result;
3701+}
3702+
3703+epicsShareFunc
3704+int osiGetInterfaceInfoSingle(const osiSockAddr *paddr, osiInterfaceInfo **presult, unsigned flags)
3705+{
3706+ ELLLIST infolist = ELLLIST_INIT;
3707+ ELLNODE *cur;
3708+ int found = 0;
3709+
3710+ if(paddr->sa.sa_family!=AF_INET)
3711+ return -1;
3712+
3713+ if(osiGetInterfaceInfo(&infolist, flags)) {
3714+ errlogPrintf ("osiGetInterfaceInfoSingle(): unable to fetch network interface configuration\n");
3715+ return -1;
3716+ }
3717+
3718+ for(cur=ellFirst(&infolist); cur; cur=ellNext(cur))
3719+ {
3720+ osiInterfaceInfo *info = CONTAINER(cur, osiInterfaceInfo, node);
3721+
3722+ if(info->address.ia.sin_addr.s_addr==paddr->ia.sin_addr.s_addr) {
3723+ if(presult) {
3724+ *presult = info;
3725+ ellDelete(&infolist, cur);
3726+ // caller now responsible to free
3727+ }
3728+ found = 1;
3729+ break;
3730+ }
3731+ }
3732+
3733+ ellFree2(&infolist, (FREEFUNC)osiFreeInterfaceInfo);
3734+ return found ? 0 : -1;
3735+}
3736+
3737
3738=== modified file 'src/libCom/osi/osiSock.h'
3739--- src/libCom/osi/osiSock.h 2016-05-22 03:43:09 +0000
3740+++ src/libCom/osi/osiSock.h 2017-05-01 18:36:52 +0000
3741@@ -155,6 +155,17 @@
3742 osiSockAddr addr;
3743 } osiSockAddrNode;
3744
3745+typedef struct {
3746+ ELLNODE node;
3747+ unsigned int up:1;
3748+ unsigned int loopback:1;
3749+ unsigned int broadcast:1;
3750+ unsigned int multicast:1;
3751+ unsigned int point2point:1;
3752+ osiSockAddr address, netmask;
3753+ osiSockAddr endpoint; //!< broadcast or p2p destination address
3754+} osiInterfaceInfo;
3755+
3756 /*
3757 * sockAddrAreIdentical()
3758 * (returns true if addresses are identical)
3759@@ -162,6 +173,32 @@
3760 epicsShareFunc int epicsShareAPI sockAddrAreIdentical
3761 ( const osiSockAddr * plhs, const osiSockAddr * prhs );
3762
3763+/* Fills the provided list with osiInterfaceInfo nodes
3764+ * describing the network interfaces of the host machine
3765+ * at the time it is called (may change later).
3766+ *
3767+ * Caller is responsible for freeing elements in the provided list with
3768+ * osiFreeInterfaceInfo(). This may be used individually, or in conjuction
3769+ * with ellFree2().
3770+ *
3771+ * flags provides for forward compatibility (eg. ipv6) and should be zero.
3772+ */
3773+epicsShareFunc int osiGetInterfaceInfo(ELLLIST *pList, unsigned flags);
3774+
3775+/* Find the interface information to the interface having address 'paddr'.
3776+ * Fills in the provided 'presults' if non-NULL, in which case the caller
3777+ * must free with osiFreeInterfaceInfo().
3778+ *
3779+ * Returns zero on success.
3780+ *
3781+ * flags provides for forward compatibility (eg. ipv6) and should be zero.
3782+ */
3783+epicsShareFunc
3784+int osiGetInterfaceInfoSingle(const osiSockAddr *paddr, osiInterfaceInfo **presult, unsigned flags);
3785+
3786+
3787+epicsShareFunc void osiFreeInterfaceInfo(osiInterfaceInfo *pinfo);
3788+
3789 /*
3790 * osiSockDiscoverBroadcastAddresses ()
3791 * Returns the broadcast addresses of each network interface found.
3792
3793=== modified file 'src/libCom/test/Makefile'
3794--- src/libCom/test/Makefile 2016-07-22 04:37:54 +0000
3795+++ src/libCom/test/Makefile 2017-05-01 18:36:52 +0000
3796@@ -86,6 +86,13 @@
3797 testHarness_SRCS += epicsSockResolveTest.c
3798 TESTS += epicsSockResolveTest
3799
3800+TESTPROD_HOST += epicsNetIntfTest
3801+epicsNetIntfTest_SRCS += epicsNetIntfTest.c
3802+epicsNetIntfTest_SYS_LIBS_solaris = socket
3803+epicsNetIntfTest_SYS_LIBS_WIN32 = ws2_32 user32
3804+testHarness_SRCS += epicsNetIntfTest.c
3805+TESTS += epicsNetIntfTest
3806+
3807 TESTPROD_HOST += epicsStringTest
3808 epicsStringTest_SRCS += epicsStringTest.c
3809 testHarness_SRCS += epicsStringTest.c
3810
3811=== modified file 'src/libCom/test/epicsMessageQueueTest.cpp'
3812--- src/libCom/test/epicsMessageQueueTest.cpp 2016-05-22 12:38:18 +0000
3813+++ src/libCom/test/epicsMessageQueueTest.cpp 2017-05-01 18:36:52 +0000
3814@@ -151,7 +151,7 @@
3815 testOk(q1->pending() == i, "q1->pending() == %d", i);
3816 }
3817 testOk1(q1->pending() == 4);
3818-
3819+
3820 want = 0;
3821 len = q1->receive(cbuf, sizeof cbuf);
3822 testOk1(q1->pending() == 3);
3823
3824=== added file 'src/libCom/test/epicsNetIntfTest.c'
3825--- src/libCom/test/epicsNetIntfTest.c 1970-01-01 00:00:00 +0000
3826+++ src/libCom/test/epicsNetIntfTest.c 2017-05-01 18:36:52 +0000
3827@@ -0,0 +1,220 @@
3828+/*************************************************************************\
3829+* Copyright (c) 2015 Brookhaven Science Associates as Operator of
3830+* Brookhaven National Lab.
3831+* EPICS BASE is distributed subject to a Software License Agreement found
3832+* in file LICENSE that is included with this distribution.
3833+\*************************************************************************/
3834+
3835+#include <stdlib.h>
3836+
3837+#include "dbDefs.h"
3838+#include "osiSock.h"
3839+#include "epicsTypes.h"
3840+
3841+#include "epicsUnitTest.h"
3842+#include "testMain.h"
3843+
3844+static
3845+void testIfInfo(void)
3846+{
3847+ int foundlo = 0, bcastok = 1;
3848+ ELLLIST iflist = ELLLIST_INIT;
3849+ ELLNODE *cur;
3850+ testDiag("Check interface introspection info");
3851+
3852+#ifdef USE_IFADDRS
3853+ testDiag("Using getifaddrs() method");
3854+#else
3855+ testDiag("Using OS default method");
3856+#endif
3857+
3858+ testOk1(osiGetInterfaceInfo(&iflist, 0)==0);
3859+
3860+ testOk(ellCount(&iflist)>0, "interface count %d", ellCount(&iflist));
3861+
3862+ for(cur=ellFirst(&iflist); cur; cur=ellNext(cur))
3863+ {
3864+ osiInterfaceInfo *info = CONTAINER(cur, osiInterfaceInfo, node);
3865+ char buf[30];
3866+
3867+ if(info->loopback) {
3868+ testOk(info->up, "loopback interface is up");
3869+ foundlo = 1;
3870+ }
3871+
3872+ if(info->address.sa.sa_family!=AF_INET)
3873+ continue;
3874+
3875+ ipAddrToDottedIP(&info->address.ia, buf, sizeof(buf));
3876+ testDiag("Address: %s", buf);
3877+ ipAddrToDottedIP(&info->netmask.ia, buf, sizeof(buf));
3878+ testDiag("Netmask: %s", buf);
3879+ if(info->broadcast) {
3880+ ipAddrToDottedIP(&info->endpoint.ia, buf, sizeof(buf));
3881+ testDiag("Broadcast: %s", buf);
3882+ } else if(info->point2point) {
3883+ ipAddrToDottedIP(&info->endpoint.ia, buf, sizeof(buf));
3884+ testDiag("Destination: %s", buf);
3885+ }
3886+
3887+ testDiag(" Up: %s", info->up?"Up":"Down");
3888+ testDiag(" Loopback: %s", info->loopback?"Yes":"No");
3889+ testDiag(" Broadcast: %s", info->broadcast?"Yes":"No");
3890+ testDiag(" Multicast: %s", info->multicast?"Yes":"No");
3891+ testDiag(" Point2Point: %s", info->point2point?"Yes":"No");
3892+
3893+ /* check consistency of address, netmask, and broadcast address */
3894+ if(info->broadcast) {
3895+ epicsUInt32 addr = ntohl(info->address.ia.sin_addr.s_addr),
3896+ mask = ntohl(info->netmask.ia.sin_addr.s_addr),
3897+ bcast = ntohl(info->endpoint.ia.sin_addr.s_addr),
3898+ bcast2= (addr&mask) | ~mask;
3899+
3900+ if(bcast!=bcast2) {
3901+ struct sockaddr_in addr;
3902+ addr.sin_family = AF_INET;
3903+ addr.sin_addr.s_addr = htonl(bcast2);
3904+ addr.sin_port = 0;
3905+ ipAddrToDottedIP(&addr, buf, sizeof(buf));
3906+ testDiag("Warning: expected broadcast address %s", buf);
3907+ bcastok = 0;
3908+ }
3909+ }
3910+ }
3911+
3912+ ellFree2(&iflist, (FREEFUNC)osiFreeInterfaceInfo);
3913+
3914+ testOk(foundlo, "Found loopback interface");
3915+ testOk(bcastok, "Broadcast addresses consistent");
3916+}
3917+
3918+static
3919+void testBroadcast(void)
3920+{
3921+ ELLLIST iflist = ELLLIST_INIT;
3922+ ELLNODE *cur;
3923+ SOCKET sock;
3924+ osiSockAddr match;
3925+
3926+ testDiag("Discover broadcast addresses");
3927+
3928+ sock = epicsSocketCreate(AF_INET, SOCK_DGRAM, 0);
3929+ if(sock==INVALID_SOCKET)
3930+ testAbort("Failed to allocate socket");
3931+
3932+ match.ia.sin_family = AF_INET;
3933+ match.ia.sin_addr.s_addr = htonl(INADDR_ANY);
3934+ match.ia.sin_port = 0;
3935+
3936+ osiSockDiscoverBroadcastAddresses(&iflist, sock, &match);
3937+
3938+ testOk(ellCount(&iflist)>0, "broadcast count %d", ellCount(&iflist));
3939+
3940+ for(cur=ellFirst(&iflist); cur; cur=ellNext(cur))
3941+ {
3942+ osiSockAddrNode *info = CONTAINER(cur, osiSockAddrNode, node);
3943+ char buf[30];
3944+
3945+ ipAddrToDottedIP(&info->addr.ia, buf, sizeof(buf));
3946+ testDiag("Broadcast: %s", buf);
3947+ }
3948+
3949+ ellFree(&iflist);
3950+
3951+ testDiag("\"Discover\" loopback address");
3952+
3953+ match.ia.sin_family = AF_INET;
3954+ match.ia.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
3955+ match.ia.sin_port = 0;
3956+
3957+ osiSockDiscoverBroadcastAddresses(&iflist, sock, &match);
3958+
3959+ testOk(ellCount(&iflist)>0, "broadcast count %d", ellCount(&iflist));
3960+
3961+ for(cur=ellFirst(&iflist); cur; cur=ellNext(cur))
3962+ {
3963+ osiSockAddrNode *info = CONTAINER(cur, osiSockAddrNode, node);
3964+ char buf[30];
3965+
3966+ ipAddrToDottedIP(&info->addr.ia, buf, sizeof(buf));
3967+ testDiag("Broadcast: %s", buf);
3968+ }
3969+
3970+ ellFree(&iflist);
3971+
3972+ epicsSocketDestroy(sock);
3973+}
3974+
3975+static
3976+void testLocal(void)
3977+{
3978+ SOCKET sock;
3979+ osiSockAddr addr;
3980+ char buf[30];
3981+
3982+ testDiag("Discover first local address");
3983+
3984+ sock = epicsSocketCreate(AF_INET, SOCK_DGRAM, 0);
3985+ if(sock==INVALID_SOCKET)
3986+ testAbort("Failed to allocate socket");
3987+
3988+ addr = osiLocalAddr(sock);
3989+
3990+ testOk1(addr.sa.sa_family==AF_INET);
3991+
3992+ ipAddrToDottedIP(&addr.ia, buf, sizeof(buf));
3993+ testDiag("Address: %s", buf);
3994+
3995+ epicsSocketDestroy(sock);
3996+}
3997+
3998+static
3999+void testBroadcastMatch(void)
4000+{
4001+ SOCKET sock;
4002+ osiSockAddr match;
4003+ ELLNODE *cur;
4004+ ELLLIST iflist = ELLLIST_INIT;
4005+ char buf[30];
4006+
4007+ testDiag("Check osiSockDiscoverBroadcastAddresses() w/ matching");
4008+
4009+ sock = epicsSocketCreate(AF_INET, SOCK_DGRAM, 0);
4010+ if(sock==INVALID_SOCKET)
4011+ testAbort("Failed to allocate socket");
4012+
4013+ match = osiLocalAddr(sock);
4014+
4015+ testOk1(match.sa.sa_family==AF_INET);
4016+ ipAddrToDottedIP(&match.ia, buf, sizeof(buf));
4017+ testDiag("Address: %s", buf);
4018+
4019+ osiSockDiscoverBroadcastAddresses(&iflist, sock, &match);
4020+
4021+ testOk(ellCount(&iflist)>0, "broadcast count %d", ellCount(&iflist));
4022+
4023+ for(cur=ellFirst(&iflist); cur; cur=ellNext(cur))
4024+ {
4025+ osiSockAddrNode *info = CONTAINER(cur, osiSockAddrNode, node);
4026+ char buf[30];
4027+
4028+ ipAddrToDottedIP(&info->addr.ia, buf, sizeof(buf));
4029+ testDiag("Broadcast: %s", buf);
4030+ }
4031+
4032+ ellFree(&iflist);
4033+
4034+ epicsSocketDestroy(sock);
4035+}
4036+
4037+MAIN(epicsNetIntfTest)
4038+{
4039+ testPlan(10);
4040+ osiSockAttach();
4041+ testIfInfo();
4042+ testBroadcast();
4043+ testLocal();
4044+ testBroadcastMatch();
4045+ osiSockRelease();
4046+ return testDone();
4047+}
4048
4049=== modified file 'src/libCom/test/epicsRunLibComTests.c'
4050--- src/libCom/test/epicsRunLibComTests.c 2016-07-22 04:37:54 +0000
4051+++ src/libCom/test/epicsRunLibComTests.c 2017-05-01 18:36:52 +0000
4052@@ -30,6 +30,7 @@
4053 int epicsMMIOTest(void);
4054 int epicsMutexTest(void);
4055 int epicsSockResolveTest(void);
4056+int epicsNetIntfTest(void);
4057 int epicsSpinTest(void);
4058 int epicsStackTraceTest(void);
4059 int epicsStdioTest(void);
4060@@ -84,6 +85,7 @@
4061 runTest(epicsMMIOTest);
4062 runTest(epicsMutexTest);
4063 runTest(epicsSockResolveTest);
4064+ runTest(epicsNetIntfTest);
4065 runTest(epicsSpinTest);
4066 runTest(epicsStackTraceTest);
4067 runTest(epicsStdioTest);
4068
4069=== modified file 'src/libCom/test/ringPointerTest.c'
4070--- src/libCom/test/ringPointerTest.c 2014-11-18 23:30:43 +0000
4071+++ src/libCom/test/ringPointerTest.c 2017-05-01 18:36:52 +0000
4072@@ -235,7 +235,6 @@
4073 MAIN(ringPointerTest)
4074 {
4075 int prio = epicsThreadGetPrioritySelf();
4076-
4077 testPlan(37);
4078 testSingle();
4079 epicsThreadSetPriority(epicsThreadGetIdSelf(), epicsThreadPriorityScanLow);

Subscribers

People subscribed via source and target branches