Merge ~epics-core/epics-base/+git/rtems5libcom:hj/rtems5libcom into ~epics-core/epics-base/+git/epics-base:libcom/master
- Git
- lp:~epics-core/epics-base/+git/rtems5libcom
- hj/rtems5libcom
- Merge into libcom/master
Status: | Rejected |
---|---|
Rejected by: | mdavidsaver |
Proposed branch: | ~epics-core/epics-base/+git/rtems5libcom:hj/rtems5libcom |
Merge into: | ~epics-core/epics-base/+git/epics-base:libcom/master |
Diff against target: |
3753 lines (+3397/-54) 48 files modified
RTEMS/Makefile (+32/-7) RTEMS/kernel/epicsRtemsInitHookPost.c (+0/-0) RTEMS/kernel/epicsRtemsInitHooks.h (+0/-0) RTEMS/kernel/rtems_config.c (+7/-6) RTEMS/kernel/rtems_init.c (+0/-0) RTEMS/kernel/rtems_netconfig.c (+56/-41) RTEMS/kernel/setBootConfigFromNVRAM.c (+0/-0) RTEMS/ne2kpci.c (+58/-0) RTEMS/posix/epicsMakeMemFs.pl (+83/-0) RTEMS/posix/epicsMemFs.c (+110/-0) RTEMS/posix/epicsMemFs.h (+24/-0) RTEMS/posix/epicsRtemsInitHookPost.c (+23/-0) RTEMS/posix/epicsRtemsInitHooks.h (+25/-0) RTEMS/posix/rtems_config.c (+88/-0) RTEMS/posix/rtems_init.c (+796/-0) RTEMS/posix/rtems_netconfig.c (+128/-0) RTEMS/posix/setBootConfigFromNVRAM.c (+458/-0) RTEMS/rtems_netconfig.h (+7/-0) src/osi/os/RTEMS-kernel/epicsAtomicOSD.cpp (+0/-0) src/osi/os/RTEMS-kernel/epicsAtomicOSD.h (+0/-0) src/osi/os/RTEMS-kernel/osdEvent.c (+0/-0) src/osi/os/RTEMS-kernel/osdEvent.h (+0/-0) src/osi/os/RTEMS-kernel/osdFindSymbol.c (+0/-0) src/osi/os/RTEMS-kernel/osdMessageQueue.c (+0/-0) src/osi/os/RTEMS-kernel/osdMessageQueue.h (+0/-0) src/osi/os/RTEMS-kernel/osdMutex.c (+0/-0) src/osi/os/RTEMS-kernel/osdMutex.h (+0/-0) src/osi/os/RTEMS-kernel/osdPoolStatus.c (+0/-0) src/osi/os/RTEMS-kernel/osdProcess.c (+0/-0) src/osi/os/RTEMS-kernel/osdReadline.c (+0/-0) src/osi/os/RTEMS-kernel/osdSignal.cpp (+0/-0) src/osi/os/RTEMS-kernel/osdSock.h (+0/-0) src/osi/os/RTEMS-kernel/osdSpin.c (+0/-0) src/osi/os/RTEMS-kernel/osdStrtod.h (+0/-0) src/osi/os/RTEMS-kernel/osdThread.c (+0/-0) src/osi/os/RTEMS-kernel/osdThread.h (+0/-0) src/osi/os/RTEMS-kernel/osdThreadExtra.c (+0/-0) src/osi/os/RTEMS-kernel/osdTime.cpp (+0/-0) src/osi/os/RTEMS-kernel/osdTime.h (+0/-0) src/osi/os/RTEMS-kernel/osiUnistd.h (+0/-0) src/osi/os/RTEMS-posix/osdInterrupt.c (+59/-0) src/osi/os/RTEMS-posix/osdMessageQueue.cpp (+163/-0) src/osi/os/RTEMS-posix/osdMessageQueue.h (+31/-0) src/osi/os/RTEMS-posix/osdMutex.c (+6/-0) src/osi/os/RTEMS-posix/osdPoolStatus.c (+34/-0) src/osi/os/RTEMS-posix/osdSock.h (+112/-0) src/osi/os/RTEMS-posix/osdThread.c (+1042/-0) src/osi/os/RTEMS-posix/osdThread.h (+55/-0) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
mdavidsaver | Disapprove | ||
Review via email: mp+342545@code.launchpad.net |
Commit message
Description of the change
Heinz Junkes (junkes) wrote : | # |
> On 5. Apr 2018, at 20:20, mdavidsaver <email address hidden> wrote:
>
> Review: Needs Fixing
>
> After a first pass reading through the diff I see two areas which need attention.
>
> 1) Parts of my RTEMS testing branch are still included. Not enough to actually work though. I'm referring to the files ne2kpci.*, epicsMakeMemFs.pl, and epicsMemFs.*. I think these could be removed with minimal effort.
Ok, thought this is a good idea to include this in rtemss5 … and only there. I had not touch the existing stuff.
>
> 2) There is still imo. too much duplication. The files I'd specifically like to see de-duplicated are: rtems_init.c, setBootConfigFr
The files are in the respective subfolders posix or kernel to be sure that the old stuff is untouched.
My first approach with ifdef's was not very nice.
mdavidsaver (mdavidsaver) wrote : | # |
I did a diff of the RTEMS-kernel/ vs. RTEMS-posix/ vs. posix/ implementations. Some notes below:
> diff -uwrN RTEMS/kernel RTEMS/posix |less
= RTEMS/*
These one might as well be different files.
= RTEMS/*
The differences here are largely due to my testing changes having been applied to the posix/ version and kernel/ version. Backing these out from the posix/ version, most of the remaining changes have to do with NFS and TFTP file systems. I think this could be further reduced. eg. the 4.10 version of nfsMount() could use mount_and_
= RTEMS/*
The diff here is smaller than I expected. Just the removal of loopback_config and not setting the bsdnet thread priority.
= RTEMS/*
I think all diff here is my doing, and should be applied to both or neither.
> diff -uwr src/osi/
Most of this diff seems to be related to changes to the checkStatus* macro definitions and usage. I didn't look at this in detail.
There is some special handling of the main() thread which seems to be duplicated in init_threadInfo() and rtemsMainInit().
The remainder looks like differences to how thread priorities are handled.
= src/osi/
A verbatim copy.
= src/osi/
Another diff which was smaller than I was expecting.
mdavidsaver (mdavidsaver) wrote : | # |
This work has moved to https:/
Unmerged commits
- bfe868e... by Heinz Junkes
-
Add support for Rtems 5
Rtems recommends the posix api for new developments to enable the use of
SMP in the future. To distinguish if posix is used the new GNUmake
variable $(OS_API) is evaluated in the makefile.
Preview Diff
1 | diff --git a/RTEMS/Makefile b/RTEMS/Makefile |
2 | index b0f3b6f..2fb2c36 100644 |
3 | --- a/RTEMS/Makefile |
4 | +++ b/RTEMS/Makefile |
5 | @@ -6,12 +6,33 @@ |
6 | # EPICS BASE is distributed subject to a Software License Agreement found |
7 | # in file LICENSE that is included with this distribution. |
8 | #************************************************************************* |
9 | - |
10 | -TOP = .. |
11 | +TOP=../../.. |
12 | include $(TOP)/configure/CONFIG |
13 | -include $(TOP)/configure/CONFIG_LIBCOM_VERSION |
14 | |
15 | -INC += epicsRtemsInitHooks.h |
16 | +SRC_IMPL_DIR = $(if $(OS_API),$(OS_API),) kernel |
17 | + |
18 | +SRC_DIRS += ../$(SRC_IMPL_DIR) |
19 | + |
20 | +ifeq ($(OS_API),posix) |
21 | +PERL_SCRIPTS += epicsMakeMemFs.pl |
22 | +endif |
23 | + |
24 | +INC += $(SRC_IMPL_DIR)/epicsRtemsInitHooks.h |
25 | + |
26 | +ifeq ($(OS_API),posix) |
27 | +INC += $(OS_API)/epicsMemFs.h |
28 | +endif |
29 | + |
30 | +ifeq ($(USE_RTEMS_GDBSTUB_$(T_A)),YES) |
31 | +rtems_init_CPPFLAGS += -DUSE_GDBSTUB |
32 | +endif |
33 | + |
34 | +ifeq ($(T_A),RTEMS-pc386) |
35 | +setBootConfigFromNVRAM_CPPFLAGS += -DUSE_MULTIBOOT |
36 | +endif |
37 | +ifeq ($(RTEMS_QEMU_FIXUPS),YES) |
38 | +rtems_init_CPPFLAGS += -DQEMU_FIXUPS |
39 | +endif |
40 | |
41 | rtemsCom_SRCS += rtems_init.c |
42 | rtemsCom_SRCS += rtems_config.c |
43 | @@ -20,10 +41,14 @@ rtemsCom_SRCS += rtems_util.c |
44 | rtemsCom_SRCS += setBootConfigFromNVRAM.c |
45 | rtemsCom_SRCS += epicsRtemsInitHookPre.c |
46 | rtemsCom_SRCS += epicsRtemsInitHookPost.c |
47 | +ifeq ($(OS_API),posix) |
48 | +rtemsCom_SRCS += epicsMemFs.c |
49 | +endif |
50 | |
51 | -LIBRARY_RTEMS = rtemsCom |
52 | +ifeq ($(T_A),RTEMS-pc386) |
53 | +rtemsCom_SRCS += ne2kpci.c |
54 | +endif |
55 | |
56 | -# shared library ABI version. |
57 | -SHRLIB_VERSION = $(EPICS_LIBCOM_MAJOR_VERSION).$(EPICS_LIBCOM_MINOR_VERSION).$(EPICS_LIBCOM_MAINTENANCE_VERSION) |
58 | +LIBRARY_RTEMS = rtemsCom |
59 | |
60 | include $(TOP)/configure/RULES |
61 | diff --git a/RTEMS/epicsRtemsInitHookPost.c b/RTEMS/kernel/epicsRtemsInitHookPost.c |
62 | index f589eb9..f589eb9 100644 |
63 | --- a/RTEMS/epicsRtemsInitHookPost.c |
64 | +++ b/RTEMS/kernel/epicsRtemsInitHookPost.c |
65 | diff --git a/RTEMS/epicsRtemsInitHooks.h b/RTEMS/kernel/epicsRtemsInitHooks.h |
66 | index b7f09c1..b7f09c1 100644 |
67 | --- a/RTEMS/epicsRtemsInitHooks.h |
68 | +++ b/RTEMS/kernel/epicsRtemsInitHooks.h |
69 | diff --git a/RTEMS/rtems_config.c b/RTEMS/kernel/rtems_config.c |
70 | index 147c08b..6612aad 100644 |
71 | --- a/RTEMS/rtems_config.c |
72 | +++ b/RTEMS/kernel/rtems_config.c |
73 | @@ -1,17 +1,17 @@ |
74 | /*************************************************************************\ |
75 | * Copyright (c) 2002 The University of Saskatchewan |
76 | -* EPICS BASE Versions 3.13.7 |
77 | -* and higher are distributed subject to a Software License Agreement found |
78 | -* in file LICENSE that is included with this distribution. |
79 | +* EPICS BASE is distributed subject to a Software License Agreement found |
80 | +* in file LICENSE that is included with this distribution. |
81 | \*************************************************************************/ |
82 | /* |
83 | * RTEMS configuration for EPICS |
84 | * Author: W. Eric Norum |
85 | - * norume@aps.anl.gov |
86 | - * (630) 252-4793 |
87 | */ |
88 | |
89 | #include <rtems.h> |
90 | +#include <epicsVersion.h> |
91 | +#define RTEMS_VERSION_INT \ |
92 | + VERSION_INT(__RTEMS_MAJOR__, __RTEMS_MINOR__, __RTEMS_REVISION__, 0) |
93 | |
94 | /* |
95 | *********************************************************************** |
96 | @@ -20,7 +20,7 @@ |
97 | */ |
98 | #define CONFIGURE_RTEMS_INIT_TASKS_TABLE |
99 | |
100 | -#if __RTEMS_MAJOR__>4 || (__RTEMS_MAJOR__==4 && __RTEMS_MINOR__>9) || (__RTEMS_MAJOR__==4 && __RTEMS_MINOR__==9 && __RTEMS_REVISION__==99) |
101 | +#if RTEMS_VERSION_INT >= VERSION_INT(4, 9, 99, 0) |
102 | # define CONFIGURE_UNIFIED_WORK_AREAS |
103 | #else |
104 | # define CONFIGURE_EXECUTIVE_RAM_SIZE (2000*1024) |
105 | @@ -54,6 +54,7 @@ rtems_task Init (rtems_task_argument argument); |
106 | #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER |
107 | #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER |
108 | |
109 | +#define CONFIGURE_FILESYSTEM_TFTPFS |
110 | #define CONFIGURE_FILESYSTEM_NFS |
111 | #define CONFIGURE_FILESYSTEM_IMFS |
112 | |
113 | diff --git a/RTEMS/rtems_init.c b/RTEMS/kernel/rtems_init.c |
114 | index 82871da..82871da 100644 |
115 | --- a/RTEMS/rtems_init.c |
116 | +++ b/RTEMS/kernel/rtems_init.c |
117 | diff --git a/RTEMS/rtems_netconfig.c b/RTEMS/kernel/rtems_netconfig.c |
118 | index 832a664..83d50dd 100644 |
119 | --- a/RTEMS/rtems_netconfig.c |
120 | +++ b/RTEMS/kernel/rtems_netconfig.c |
121 | @@ -16,58 +16,75 @@ |
122 | #include <bsp.h> |
123 | #include <rtems/rtems_bsdnet.h> |
124 | |
125 | +#include "rtems_netconfig.h" |
126 | + |
127 | extern void rtems_bsdnet_loopattach(); |
128 | static struct rtems_bsdnet_ifconfig loopback_config = { |
129 | "lo0", /* name */ |
130 | - (int (*)(struct rtems_bsdnet_ifconfig *, int))rtems_bsdnet_loopattach, /* attach function */ |
131 | - NULL, /* link to next interface */ |
132 | + (int (*)(struct rtems_bsdnet_ifconfig *, int))rtems_bsdnet_loopattach, |
133 | + NULL, /* last interface */ |
134 | "127.0.0.1", /* IP address */ |
135 | "255.0.0.0", /* IP net mask */ |
136 | }; |
137 | |
138 | +#define stringOf(x) #x |
139 | +#define STRING(x) stringOf(x) |
140 | + |
141 | /* |
142 | - * The following conditionals select the network interface card. |
143 | - * |
144 | - * On RTEMS-pc386 targets all network drivers which support run-time |
145 | - * probing are linked. |
146 | - * On other targets the network interface specified by the board-support |
147 | - * package is used. |
148 | - * To use a different NIC for a particular application, copy this file to the |
149 | - * application directory and make the appropriate changes. |
150 | + * The following configures up to 2 network interface card(s) using |
151 | + * settings in either configure/os/CONFIG_SITE.Common.RTEMS or in a |
152 | + * BSP-specific configure/os/CONFIG_SITE.Common.RTEMS-<bsp> file. |
153 | + * If no settings are provided, it uses the BSP's defaults instead. |
154 | */ |
155 | -#if defined(__i386__) |
156 | -extern int rtems_fxp_attach (struct rtems_bsdnet_ifconfig *, int); |
157 | -static struct rtems_bsdnet_ifconfig fxp_driver_config = { |
158 | - "fxp1", /* name */ |
159 | - rtems_fxp_attach, /* attach function */ |
160 | - &loopback_config, /* link to next interface */ |
161 | -}; |
162 | -extern int rtems_3c509_driver_attach (struct rtems_bsdnet_ifconfig *, int); |
163 | -static struct rtems_bsdnet_ifconfig e3c509_driver_config = { |
164 | - "ep0", /* name */ |
165 | - rtems_3c509_driver_attach, /* attach function */ |
166 | - &fxp_driver_config, /* link to next interface */ |
167 | -}; |
168 | -#define FIRST_DRIVER_CONFIG &e3c509_driver_config |
169 | -#else |
170 | |
171 | -# if defined(__PPC) |
172 | - /* |
173 | - * FIXME: This really belongs in the BSP |
174 | - */ |
175 | -# ifndef RTEMS_BSP_NETWORK_DRIVER_NAME |
176 | -# define RTEMS_BSP_NETWORK_DRIVER_NAME "dc1" |
177 | -# endif |
178 | -# ifndef RTEMS_BSP_NETWORK_DRIVER_ATTACH |
179 | -# define RTEMS_BSP_NETWORK_DRIVER_ATTACH rtems_dec21140_driver_attach |
180 | - extern int rtems_dec21140_driver_attach(); |
181 | -# endif |
182 | -# endif |
183 | +#if defined(RTEMS_NETWORK_DRIVER_NAME_1) |
184 | + |
185 | + #if defined(RTEMS_NETWORK_DRIVER_NAME_2) |
186 | + static struct rtems_bsdnet_ifconfig netdriver_config_2 = { |
187 | + STRING(RTEMS_NETWORK_DRIVER_NAME_2), |
188 | + #if defined(RTEMS_NETWORK_DRIVER_ATTACH_2) |
189 | + RTEMS_NETWORK_DRIVER_ATTACH_2, /* specific attach function */ |
190 | + #else |
191 | + RTEMS_BSP_NETWORK_DRIVER_ATTACH, /* default attach function */ |
192 | + #endif |
193 | + &loopback_config, /* loopback interface */ |
194 | + #if defined(RTEMS_NETWORK_IP4_ADDR_2) |
195 | + STRING(RTEMS_NETWORK_IP4_ADDR_2), |
196 | + #if defined(RTEMS_NETWORK_IP4_MASK_2) |
197 | + STRING(RTEMS_NETWORK_IP4_MASK_2), |
198 | + #endif |
199 | + #endif |
200 | + }; |
201 | + #endif /* RTEMS_NETWORK_DRIVER_NAME_2 */ |
202 | + |
203 | + static struct rtems_bsdnet_ifconfig netdriver_config = { |
204 | + STRING(RTEMS_NETWORK_DRIVER_NAME_1), |
205 | + #if defined(RTEMS_NETWORK_DRIVER_ATTACH_1) |
206 | + RTEMS_NETWORK_DRIVER_ATTACH_1, /* specific attach function */ |
207 | + #else |
208 | + RTEMS_BSP_NETWORK_DRIVER_ATTACH, /* default attach function */ |
209 | + #endif |
210 | + #if defined(RTEMS_NETWORK_DRIVER_NAME_2) |
211 | + &netdriver_config_2, /* link to next interface */ |
212 | + #else |
213 | + &loopback_config, /* loopback interface */ |
214 | + #endif |
215 | + #if defined(RTEMS_NETWORK_IP4_ADDR_1) |
216 | + STRING(RTEMS_NETWORK_IP4_ADDR_1), |
217 | + #if defined(RTEMS_NETWORK_IP4_MASK_1) |
218 | + STRING(RTEMS_NETWORK_IP4_MASK_1), |
219 | + #endif |
220 | + #endif |
221 | + }; |
222 | + #define FIRST_DRIVER_CONFIG &netdriver_config |
223 | + |
224 | +#else /* RTEMS_NETWORK_DRIVER_NAME_1 */ |
225 | |
226 | +/* Use the BSP-provided standard macros */ |
227 | static struct rtems_bsdnet_ifconfig bsp_driver_config = { |
228 | RTEMS_BSP_NETWORK_DRIVER_NAME, /* name */ |
229 | RTEMS_BSP_NETWORK_DRIVER_ATTACH, /* attach function */ |
230 | - &loopback_config, /* link to next interface */ |
231 | + &loopback_config, /* loopback interface */ |
232 | }; |
233 | #define FIRST_DRIVER_CONFIG &bsp_driver_config |
234 | |
235 | @@ -77,9 +94,7 @@ static struct rtems_bsdnet_ifconfig bsp_driver_config = { |
236 | * Allow configure/os/CONFIG_SITE.Common.RTEMS to provide domain name |
237 | */ |
238 | #ifdef RTEMS_NETWORK_CONFIG_DNS_DOMAINNAME |
239 | -# define XSTR(x) STR(x) |
240 | -# define STR(x) #x |
241 | -# define MY_DOMAINNAME XSTR(RTEMS_NETWORK_CONFIG_DNS_DOMAINNAME) |
242 | +# define MY_DOMAINNAME STRING(RTEMS_NETWORK_CONFIG_DNS_DOMAINNAME) |
243 | #else |
244 | # define MY_DOMAINNAME NULL |
245 | #endif |
246 | diff --git a/RTEMS/setBootConfigFromNVRAM.c b/RTEMS/kernel/setBootConfigFromNVRAM.c |
247 | index 6a162c6..6a162c6 100644 |
248 | --- a/RTEMS/setBootConfigFromNVRAM.c |
249 | +++ b/RTEMS/kernel/setBootConfigFromNVRAM.c |
250 | diff --git a/RTEMS/ne2kpci.c b/RTEMS/ne2kpci.c |
251 | new file mode 100644 |
252 | index 0000000..909d885 |
253 | --- /dev/null |
254 | +++ b/RTEMS/ne2kpci.c |
255 | @@ -0,0 +1,58 @@ |
256 | +/*************************************************************************\ |
257 | +* Copyright (c) 2015 Brookhaven Science Associates, as Operator of |
258 | +* Brookhaven National Laboratory. |
259 | +* EPICS BASE is distributed subject to a Software License Agreement found |
260 | +* in file LICENSE that is included with this distribution. |
261 | +\*************************************************************************/ |
262 | +/* |
263 | + * Wrapper around the ISA ne2000 driver to support detection of the PCI variant. |
264 | + * Can be used with the ne2k_pci device provided by QEMU. |
265 | + * |
266 | + * eg. "qemu-system-i386 ... -net nic,model=ne2k_pci" |
267 | + */ |
268 | + |
269 | +#include <stdio.h> |
270 | +#include <inttypes.h> |
271 | +#include <bsp.h> |
272 | +#include <rtems/pci.h> |
273 | +#include <rtems/rtems_bsdnet.h> |
274 | + |
275 | +/* The plain ISA driver attach() |
276 | + * which doesn't (can't?) do any test to see if |
277 | + * the HW is really present |
278 | + */ |
279 | +extern int |
280 | +rtems_ne_driver_attach (struct rtems_bsdnet_ifconfig *config, int attach); |
281 | + |
282 | +int |
283 | +rtems_ne2kpci_driver_attach (struct rtems_bsdnet_ifconfig *config, int attach) |
284 | +{ |
285 | + uint8_t irq; |
286 | + uint32_t bar0; |
287 | + int B, D, F, ret; |
288 | + printk("Probing for NE2000 on PCI (aka. Realtek 8029)\n"); |
289 | + |
290 | + if(pci_find_device(PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8029, 0, &B, &D, &F)) |
291 | + { |
292 | + printk("Not found\n"); |
293 | + return 0; |
294 | + } |
295 | + |
296 | + printk("Found %d:%d.%d\n", B, D, F); |
297 | + |
298 | + ret = pci_read_config_dword(B, D, F, PCI_BASE_ADDRESS_0, &bar0); |
299 | + ret|= pci_read_config_byte(B, D, F, PCI_INTERRUPT_LINE, &irq); |
300 | + |
301 | + if(ret || (bar0&PCI_BASE_ADDRESS_SPACE)!=PCI_BASE_ADDRESS_SPACE_IO) |
302 | + { |
303 | + printk("Failed reading card config\n"); |
304 | + return 0; |
305 | + } |
306 | + |
307 | + config->irno = irq; |
308 | + config->port = bar0&PCI_BASE_ADDRESS_IO_MASK; |
309 | + |
310 | + printk("Using port=0x%x irq=%u\n", (unsigned)config->port, config->irno); |
311 | + |
312 | + return rtems_ne_driver_attach(config, attach); |
313 | +} |
314 | diff --git a/RTEMS/posix/epicsMakeMemFs.pl b/RTEMS/posix/epicsMakeMemFs.pl |
315 | new file mode 100644 |
316 | index 0000000..a97074e |
317 | --- /dev/null |
318 | +++ b/RTEMS/posix/epicsMakeMemFs.pl |
319 | @@ -0,0 +1,83 @@ |
320 | +#!/usr/bin/env perl |
321 | +# |
322 | + |
323 | +use File::Basename; |
324 | + |
325 | +use strict; |
326 | + |
327 | +my $outfile = shift; |
328 | +my $varname = shift; |
329 | + |
330 | +open(my $DST, '>', $outfile) or die "Failed to open $outfile"; |
331 | + |
332 | +print $DST <<EOF; |
333 | +#include <epicsMemFs.h> |
334 | +EOF |
335 | + |
336 | +my $N = 0; |
337 | + |
338 | +for my $fname (@ARGV) { |
339 | + print "<- $fname\n"; |
340 | + my $realfname = $fname; |
341 | + |
342 | + # strip leading "../" "./" or "/" |
343 | + while ($fname =~ /^\.*\/(.*)$/) { $fname = $1; } |
344 | + |
345 | + my $file = basename($fname); |
346 | + my @dirs = split('/', dirname($fname)); |
347 | + |
348 | + print $DST "/* begin $realfname */\nstatic const char * const file_${N}_dir[] = {"; |
349 | + for my $dpart (@dirs) { |
350 | + print $DST "\"$dpart\", "; |
351 | + } |
352 | + print $DST "NULL};\nstatic const char file_${N}_data[] = {\n "; |
353 | + |
354 | + open(my $SRC, '<', $realfname) or die "Failed to open $realfname"; |
355 | + binmode($SRC); |
356 | + |
357 | + my $buf; |
358 | + my $total = 0; |
359 | + while (my $num = read($SRC, $buf, 32)) { |
360 | + if($total != 0) { |
361 | + print $DST ",\n "; |
362 | + } |
363 | + $total += $num; |
364 | + my $out = join(",",map(ord,split(//,$buf))); |
365 | + print $DST "$out"; |
366 | + } |
367 | + |
368 | + close($SRC); |
369 | + |
370 | + print $DST <<EOF; |
371 | + |
372 | +}; |
373 | +static const epicsMemFile file_${N} = { |
374 | + file_${N}_dir, |
375 | + \"$file\", |
376 | + file_${N}_data, |
377 | + $total |
378 | +}; |
379 | +/* end $realfname */ |
380 | +EOF |
381 | + $N = $N + 1; |
382 | +} |
383 | + |
384 | +print $DST <<EOF; |
385 | +static const epicsMemFile* files[] = { |
386 | +EOF |
387 | + |
388 | +$N = $N - 1; |
389 | + |
390 | +for my $i (0..${N}) { |
391 | + print $DST " &file_${i},"; |
392 | +} |
393 | + |
394 | +print $DST <<EOF; |
395 | + NULL |
396 | +}; |
397 | +static |
398 | +const epicsMemFS ${varname}_image = {&files[0]}; |
399 | +const epicsMemFS * $varname = &${varname}_image; |
400 | +EOF |
401 | + |
402 | +close($DST); |
403 | diff --git a/RTEMS/posix/epicsMemFs.c b/RTEMS/posix/epicsMemFs.c |
404 | new file mode 100644 |
405 | index 0000000..4689d21 |
406 | --- /dev/null |
407 | +++ b/RTEMS/posix/epicsMemFs.c |
408 | @@ -0,0 +1,110 @@ |
409 | +/*************************************************************************\ |
410 | +* Copyright (c) 2014 Brookhaven National Laboratory. |
411 | +* EPICS BASE is distributed subject to a Software License Agreement found |
412 | +* in file LICENSE that is included with this distribution. |
413 | +\*************************************************************************/ |
414 | + |
415 | +#include <stdlib.h> |
416 | +#include <stdio.h> |
417 | +#include <errno.h> |
418 | + |
419 | +#include <unistd.h> |
420 | +#include <sys/stat.h> |
421 | +#include <sys/types.h> |
422 | +#include <fcntl.h> |
423 | + |
424 | +#include "epicsMemFs.h" |
425 | + |
426 | +#ifndef PATH_MAX |
427 | +# define PATH_MAX 100 |
428 | +#endif |
429 | + |
430 | +int epicsMemFsLoad(const epicsMemFS *fs) |
431 | +{ |
432 | + char initdir[PATH_MAX]; |
433 | + const epicsMemFile * const *fileptr = fs->files; |
434 | + |
435 | + if(getcwd(initdir, sizeof(initdir)-1)==NULL) { |
436 | + perror("getcwd"); |
437 | + return errno; |
438 | + } |
439 | + initdir[sizeof(initdir)-1] = '\0'; |
440 | + |
441 | + for(;*fileptr; fileptr++) { |
442 | + const epicsMemFile *curfile = *fileptr; |
443 | + int fd; |
444 | + ssize_t ret; |
445 | + size_t sofar; |
446 | + const char * const *dir = curfile->directory; |
447 | + /* jump back to the root each time, |
448 | + * slow but simple. |
449 | + */ |
450 | + if(chdir(initdir)) { |
451 | + perror("chdir"); |
452 | + return errno; |
453 | + } |
454 | + |
455 | + printf("-> /"); |
456 | + |
457 | + /* traverse directory tree, creating as necessary */ |
458 | + for(;*dir; dir++) { |
459 | + int ret; |
460 | + if(**dir=='.') continue; /* ignore '.' and '..' */ |
461 | + printf("%s/", *dir); |
462 | + ret = chdir(*dir); |
463 | + if(ret==-1 && errno==ENOENT) { |
464 | + /* this directory doesn't exist */ |
465 | + if(mkdir(*dir,0744)==-1) { |
466 | + printf("\n"); |
467 | + perror("mkdir"); |
468 | + return errno; |
469 | + } |
470 | + if(chdir(*dir)==-1) { |
471 | + printf("\n"); |
472 | + perror("chdir2"); |
473 | + return errno; |
474 | + } |
475 | + } else if(ret==-1) { |
476 | + printf("\n"); |
477 | + perror("chdir1"); |
478 | + return errno; |
479 | + } |
480 | + } |
481 | + |
482 | + /* no file name creates an empty directory */ |
483 | + if(!curfile->name) { |
484 | + printf("\n"); |
485 | + continue; |
486 | + } |
487 | + printf("%s", curfile->name); |
488 | + |
489 | + /* create or overwrite */ |
490 | + fd = open(curfile->name, O_WRONLY|O_CREAT|O_TRUNC, 0644); |
491 | + |
492 | + if(fd==-1) { |
493 | + printf("\n"); |
494 | + perror("open"); |
495 | + return errno; |
496 | + } |
497 | + |
498 | + sofar = 0; |
499 | + |
500 | + while(sofar<curfile->size) { |
501 | + ret = write(fd, curfile->data+sofar, curfile->size-sofar); |
502 | + if(ret<=0) { |
503 | + printf("\n"); |
504 | + perror("write"); |
505 | + return errno; |
506 | + } |
507 | + sofar += ret; |
508 | + } |
509 | + |
510 | + close(fd); |
511 | + printf(" - ok\n"); |
512 | + } |
513 | + |
514 | + if(chdir(initdir)) |
515 | + perror("chdir"); |
516 | + |
517 | + return 0; |
518 | +} |
519 | diff --git a/RTEMS/posix/epicsMemFs.h b/RTEMS/posix/epicsMemFs.h |
520 | new file mode 100644 |
521 | index 0000000..c57f4d7 |
522 | --- /dev/null |
523 | +++ b/RTEMS/posix/epicsMemFs.h |
524 | @@ -0,0 +1,24 @@ |
525 | +/*************************************************************************\ |
526 | +* Copyright (c) 2014 Brookhaven National Laboratory. |
527 | +* EPICS BASE is distributed subject to a Software License Agreement found |
528 | +* in file LICENSE that is included with this distribution. |
529 | +\*************************************************************************/ |
530 | +#ifndef EPICSMEMFS_H |
531 | +#define EPICSMEMFS_H |
532 | + |
533 | +#include <stdlib.h> |
534 | + |
535 | +typedef struct { |
536 | + const char * const *directory; /* NULL terminated list of directories */ |
537 | + const char *name; /* file name */ |
538 | + const char *data; /* file contents */ |
539 | + size_t size; /* size of file contents in bytes */ |
540 | +} epicsMemFile; |
541 | + |
542 | +typedef struct { |
543 | + const epicsMemFile * const *files; |
544 | +} epicsMemFS; |
545 | + |
546 | +int epicsMemFsLoad(const epicsMemFS *fs); |
547 | + |
548 | +#endif // EPICSMEMFS_H |
549 | diff --git a/RTEMS/posix/epicsRtemsInitHookPost.c b/RTEMS/posix/epicsRtemsInitHookPost.c |
550 | new file mode 100644 |
551 | index 0000000..9d8ef65 |
552 | --- /dev/null |
553 | +++ b/RTEMS/posix/epicsRtemsInitHookPost.c |
554 | @@ -0,0 +1,23 @@ |
555 | +/*************************************************************************\ |
556 | +* Copyright (c) 2006 The University of Chicago, as Operator of Argonne |
557 | +* National Laboratory. |
558 | +* EPICS BASE Versions 3.13.7 |
559 | +* and higher are distributed subject to a Software License Agreement found |
560 | +* in file LICENSE that is included with this distribution. |
561 | +\*************************************************************************/ |
562 | + |
563 | +/* |
564 | + * Dummy version -- use if application does not provide its own version |
565 | + */ |
566 | +#include "epicsRtemsInitHooks.h" |
567 | + |
568 | +int |
569 | +epicsRtemsInitPostSetBootConfigFromNVRAM(struct rtems_bsdnet_config *config) |
570 | +{ |
571 | + return 0; |
572 | +} |
573 | + |
574 | + |
575 | + |
576 | +void bootpFallbackFromNVRAM(void) __attribute__((weak)); |
577 | +void bootpFallbackFromNVRAM(void) {} |
578 | diff --git a/RTEMS/posix/epicsRtemsInitHooks.h b/RTEMS/posix/epicsRtemsInitHooks.h |
579 | new file mode 100644 |
580 | index 0000000..4313f19 |
581 | --- /dev/null |
582 | +++ b/RTEMS/posix/epicsRtemsInitHooks.h |
583 | @@ -0,0 +1,25 @@ |
584 | +/*************************************************************************\ |
585 | +* Copyright (c) 2006 The University of Chicago, as Operator of Argonne |
586 | +* National Laboratory. |
587 | +* EPICS BASE Versions 3.13.7 |
588 | +* and higher are distributed subject to a Software License Agreement found |
589 | +* in file LICENSE that is included with this distribution. |
590 | +\*************************************************************************/ |
591 | + |
592 | +/* |
593 | + * Hooks into RTEMS startup code |
594 | + */ |
595 | +#include <bsp.h> |
596 | +#include <rtems/rtems_bsdnet.h> |
597 | + |
598 | +extern char *env_nfsServer; |
599 | +extern char *env_nfsPath; |
600 | +extern char *env_nfsMountPoint; |
601 | + |
602 | +/* |
603 | + * Return 0 for success, non-zero for failure (will cause panic) |
604 | + */ |
605 | +int epicsRtemsInitPreSetBootConfigFromNVRAM(struct rtems_bsdnet_config *config); |
606 | +int epicsRtemsInitPostSetBootConfigFromNVRAM(struct rtems_bsdnet_config *config); |
607 | +/* Return 0 if local file system was setup, or non-zero (will fall back to network */ |
608 | +int epicsRtemsMountLocalFilesystem(char **argv); |
609 | diff --git a/RTEMS/posix/rtems_config.c b/RTEMS/posix/rtems_config.c |
610 | new file mode 100644 |
611 | index 0000000..8eb71eb |
612 | --- /dev/null |
613 | +++ b/RTEMS/posix/rtems_config.c |
614 | @@ -0,0 +1,88 @@ |
615 | +/*************************************************************************\ |
616 | +* Copyright (c) 2002 The University of Saskatchewan |
617 | +* Copyright (c) 2017 Fritz-Haber-Institut der Max-Planck-Gesellschaft |
618 | +* EPICS BASE is distributed subject to a Software License Agreement found |
619 | +* in file LICENSE that is included with this distribution. |
620 | +\*************************************************************************/ |
621 | +/* |
622 | + * RTEMS configuration for EPICS |
623 | + * Author: W. Eric Norum |
624 | + * Heinz Junkes |
625 | + * |
626 | + * Version for RTEMS-5 and higher |
627 | + */ |
628 | + |
629 | +#include <rtems.h> |
630 | + |
631 | +/* |
632 | + *********************************************************************** |
633 | + * RTEMS CONFIGURATION * |
634 | + *********************************************************************** |
635 | + */ |
636 | + |
637 | +extern void *POSIX_Init(void *argument); |
638 | + |
639 | +#define CONFIGURE_POSIX_INIT_THREAD_TABLE |
640 | +// Entry Point defaults to POSIX_Init |
641 | +/* |
642 | + * nfs is using rtems tasks |
643 | + */ |
644 | +#define CONFIGURE_MAXIMUM_TASKS 5 |
645 | +#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES 5 |
646 | +#define CONFIGURE_MAXIMUM_SEMAPHORES 5 |
647 | +#define CONFIGURE_MAXIMUM_EVENTS 5 |
648 | + |
649 | +#define CONFIGURE_MAXIMUM_POSIX_MUTEXES 500 |
650 | +#define CONFIGURE_MAXIMUM_POSIX_THREADS 200 |
651 | +#define CONFIGURE_MAXIMUM_POSIX_KEYS 200 |
652 | +#define CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS 200 |
653 | +#define CONFIGURE_MAXIMUM_POSIX_SPINLOCKS 100 |
654 | +#define CONFIGURE_MAXIMUM_POSIX_SEMAPHORES 300 |
655 | +#define CONFIGURE_MAXIMUM_POSIX_TIMERS 100 |
656 | +#define CONFIGURE_MAXIMUM_POSIX_MESSAGE_QUEUES 200 |
657 | +#define CONFIGURE_MAXIMUM_POSIX_CONDITION_VARIABLES 400 |
658 | + |
659 | +#define CONFIGURE_UNIFIED_WORK_AREAS |
660 | + |
661 | +#define CONFIGURE_MAXIMUM_PERIODS 5 |
662 | +#define CONFIGURE_MICROSECONDS_PER_TICK 10000 |
663 | +#define CONFIGURE_MALLOC_STATISTICS 1 |
664 | +/* MINIMUM_STACK_SIZE == 8K */ |
665 | +#define CONFIGURE_EXTRA_TASK_STACKS (4000 * RTEMS_MINIMUM_STACK_SIZE) |
666 | + |
667 | +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER |
668 | +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER |
669 | + |
670 | +#define CONFIGURE_FILESYSTEM_DEVFS |
671 | +#define CONFIGURE_FILESYSTEM_TFTPFS |
672 | +#define CONFIGURE_FILESYSTEM_NFS |
673 | +#define CONFIGURE_FILESYSTEM_IMFS |
674 | +#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM |
675 | +#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 150 |
676 | + |
677 | +#define CONFIGURE_MAXIMUM_NFS_MOUNTS 3 |
678 | +#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 5 |
679 | + |
680 | +#define CONFIGURE_POSIX_INIT_THREAD_STACK_SIZE (64*1024) |
681 | + |
682 | +#define CONFIGURE_MAXIMUM_DRIVERS 8 |
683 | + |
684 | +//#define CONFIGURE_INITIAL_EXTENSIONS { .fatal = fatal_extension } |
685 | + |
686 | +#define CONFIGURE_INIT |
687 | + |
688 | + |
689 | +/* |
690 | + * This should be made BSP dependent, not CPU dependent but I know of no |
691 | + * appropriate conditionals to use. |
692 | + * The new general time support makes including the RTC driver less important. |
693 | + */ |
694 | +#if !defined(mpc604) && !defined(__mc68040__) && !defined(__mcf5200__) && \ |
695 | + !defined(mpc7455) && !defined(__arm__) && !defined(__nios2__) |
696 | + /* don't have RTC code */ |
697 | +#define CONFIGURE_APPLICATION_NEEDS_RTC_DRIVER |
698 | +#endif |
699 | + |
700 | + |
701 | +#include <bsp.h> |
702 | +#include <rtems/confdefs.h> |
703 | diff --git a/RTEMS/posix/rtems_init.c b/RTEMS/posix/rtems_init.c |
704 | new file mode 100644 |
705 | index 0000000..a1904e7 |
706 | --- /dev/null |
707 | +++ b/RTEMS/posix/rtems_init.c |
708 | @@ -0,0 +1,796 @@ |
709 | +/*************************************************************************\ |
710 | +* Copyright (c) 2002 The University of Saskatchewan |
711 | +* Copyright (c) 2018 Fritz-Haber-Institut der Max-Planck-Gesellschaft |
712 | +* EPICS BASE is distributed subject to a Software License Agreement found |
713 | +* in file LICENSE that is included with this distribution. |
714 | +\*************************************************************************/ |
715 | +/* |
716 | + * RTEMS startup task for EPICS |
717 | + * Author: W. Eric Norum |
718 | + * Heinz Junkes |
719 | + * |
720 | + * Version for RTEMS-5 and higher |
721 | + */ |
722 | +#include <stdio.h> |
723 | +#include <stdlib.h> |
724 | +#include <string.h> |
725 | +#include <ctype.h> |
726 | +#include <time.h> |
727 | +#include <errno.h> |
728 | +#include <fcntl.h> |
729 | +#include <unistd.h> |
730 | +#include <sys/types.h> |
731 | +#include <sys/stat.h> |
732 | +#include <sys/socket.h> |
733 | +#include <netinet/in.h> |
734 | +#include <arpa/inet.h> |
735 | +#include <rtems.h> |
736 | +#include <epicsVersion.h> |
737 | +#define RTEMS_VERSION_INT \ |
738 | + VERSION_INT(__RTEMS_MAJOR__, __RTEMS_MINOR__, __RTEMS_REVISION__, 0) |
739 | +#include <rtems/malloc.h> |
740 | +#include <rtems/error.h> |
741 | +#include <rtems/stackchk.h> |
742 | +#include <rtems/rtems_bsdnet.h> |
743 | +#include <rtems/imfs.h> |
744 | +#include <rtems/tftp.h> |
745 | +#include <librtemsNfs.h> |
746 | +#include <pthread.h> |
747 | +#include <signal.h> |
748 | +#include <sched.h> |
749 | +#include <rtems/libio.h> |
750 | +#include <sys/stat.h> |
751 | +#include <termios.h> |
752 | +#include <bsp.h> |
753 | + |
754 | +#ifdef USE_GDBSTUB |
755 | +#include <rtems-gdb-stub.h> |
756 | +#endif |
757 | + |
758 | +#include "epicsThread.h" |
759 | +#include "epicsTime.h" |
760 | +#include "epicsExit.h" |
761 | +#include "envDefs.h" |
762 | +#include "errlog.h" |
763 | +#include "logClient.h" |
764 | +#include "osiUnistd.h" |
765 | +#include "iocsh.h" |
766 | +#include "osdTime.h" |
767 | +#include "epicsMemFs.h" |
768 | + |
769 | +#include "epicsRtemsInitHooks.h" |
770 | +#include <rtems/malloc.h> |
771 | +#include <rtems/score/heap.h> |
772 | +#include <pthread.h> |
773 | +#include <assert.h> |
774 | +#define rtems_test_assert(_a) assert(_a) |
775 | + |
776 | +/* |
777 | + * Prototypes for some functions not in header files |
778 | + */ |
779 | +void tzset(void); |
780 | +int fileno(FILE *); |
781 | +int main(int argc, char **argv); |
782 | + |
783 | +static void |
784 | +logReset (void) |
785 | +{ |
786 | + void rtems_bsp_reset_cause(char *buf, size_t capacity) __attribute__((weak)); |
787 | + void (*fp)(char *buf, size_t capacity) = rtems_bsp_reset_cause; |
788 | + |
789 | + if (fp) { |
790 | + char buf[80]; |
791 | + fp(buf, sizeof buf); |
792 | + errlogPrintf("Startup after %s.\n", buf); |
793 | + } |
794 | + else { |
795 | + errlogPrintf("Startup.\n"); |
796 | + } |
797 | +} |
798 | + |
799 | +/* |
800 | + *********************************************************************** |
801 | + * FATAL ERROR REPORTING * |
802 | + *********************************************************************** |
803 | + */ |
804 | +/* |
805 | + * Delay for a while, then terminate |
806 | + */ |
807 | +static void |
808 | +delayedPanic (const char *msg) |
809 | +{ |
810 | + rtems_task_wake_after (rtems_clock_get_ticks_per_second()); |
811 | + rtems_task_wake_after (rtems_clock_get_ticks_per_second()); |
812 | + rtems_panic (msg); |
813 | +} |
814 | + |
815 | +/* |
816 | + * Log error and terminate |
817 | + */ |
818 | +void |
819 | +LogFatal (const char *msg, ...) |
820 | +{ |
821 | + va_list ap; |
822 | + |
823 | + va_start (ap, msg); |
824 | + errlogVprintf (msg, ap); |
825 | + va_end (ap); |
826 | + delayedPanic (msg); |
827 | +} |
828 | + |
829 | +/* |
830 | + * Log RTEMS error and terminate |
831 | + */ |
832 | +void |
833 | +LogRtemsFatal (const char *msg, rtems_status_code sc) |
834 | +{ |
835 | + errlogPrintf ("%s: %s\n", msg, rtems_status_text (sc)); |
836 | + delayedPanic (msg); |
837 | +} |
838 | + |
839 | +/* |
840 | + * Log network error and terminate |
841 | + */ |
842 | +void |
843 | +LogNetFatal (const char *msg, int err) |
844 | +{ |
845 | + errlogPrintf ("%s: %d\n", msg, err); |
846 | + delayedPanic (msg); |
847 | +} |
848 | + |
849 | +void * |
850 | +mustMalloc(int size, const char *msg) |
851 | +{ |
852 | + void *p; |
853 | + |
854 | + if ((p = malloc (size)) == NULL) |
855 | + LogFatal ("Can't allocate space for %s.\n", msg); |
856 | + return p; |
857 | +} |
858 | + |
859 | +/* |
860 | + *********************************************************************** |
861 | + * REMOTE FILE ACCESS * |
862 | + *********************************************************************** |
863 | + */ |
864 | +#ifdef OMIT_NFS_SUPPORT |
865 | +# include <rtems/tftp.h> |
866 | +#endif |
867 | + |
868 | +const epicsMemFS *epicsRtemsFSImage __attribute__((weak)); |
869 | +const epicsMemFS *epicsRtemsFSImage = (void*)&epicsRtemsFSImage; |
870 | + |
871 | +/* hook to allow app specific FS setup */ |
872 | +int |
873 | +epicsRtemsMountLocalFilesystem(char **argv) __attribute__((weak)); |
874 | +int |
875 | +epicsRtemsMountLocalFilesystem(char **argv) |
876 | +{ |
877 | + if(epicsRtemsFSImage==(void*)&epicsRtemsFSImage) |
878 | + return -1; /* no FS image provided. */ |
879 | + else if(epicsRtemsFSImage==NULL) |
880 | + return 0; /* no FS image provided, but none is needed. */ |
881 | + else { |
882 | + printf("***** Using compiled in file data *****\n"); |
883 | + if (epicsMemFsLoad(epicsRtemsFSImage) != 0) { |
884 | + printf("Can't unpack tar filesystem\n"); |
885 | + return -1; |
886 | + } else { |
887 | + argv[1] = "/"; |
888 | + return 0; |
889 | + } |
890 | + } |
891 | +} |
892 | + |
893 | +static int |
894 | +initialize_local_filesystem(char **argv) |
895 | +{ |
896 | + extern char _DownloadLocation[] __attribute__((weak)); |
897 | + extern char _FlashBase[] __attribute__((weak)); |
898 | + extern char _FlashSize[] __attribute__((weak)); |
899 | + |
900 | + argv[0] = rtems_bsdnet_bootp_boot_file_name; |
901 | + if (epicsRtemsMountLocalFilesystem(argv)==0) { |
902 | + return 1; /* FS setup successful */ |
903 | + } else if (_FlashSize && (_DownloadLocation || _FlashBase)) { |
904 | + extern char _edata[]; |
905 | + size_t flashIndex = _edata - _DownloadLocation; |
906 | + char *header = _FlashBase + flashIndex; |
907 | + |
908 | + if (memcmp(header + 257, "ustar ", 8) == 0) { |
909 | + int fd; |
910 | + printf ("***** Unpack in-memory file system (IMFS) *****\n"); |
911 | + if (rtems_tarfs_load("/", (unsigned char *)header, (size_t)_FlashSize - flashIndex) != 0) { |
912 | + printf("Can't unpack tar filesystem\n"); |
913 | + return 0; |
914 | + } |
915 | + if ((fd = open(rtems_bsdnet_bootp_cmdline, 0)) >= 0) { |
916 | + close(fd); |
917 | + printf ("***** Found startup script (%s) in IMFS *****\n", rtems_bsdnet_bootp_cmdline); |
918 | + argv[1] = rtems_bsdnet_bootp_cmdline; |
919 | + return 1; |
920 | + } |
921 | + printf ("***** Startup script (%s) not in IMFS *****\n", rtems_bsdnet_bootp_cmdline); |
922 | + } |
923 | + } |
924 | + return 0; |
925 | +} |
926 | + |
927 | +#ifndef OMIT_NFS_SUPPORT |
928 | +int |
929 | +nfsMount(char *uidhost, char *path, char *mntpoint) |
930 | +{ |
931 | + int devl = strlen(uidhost) + strlen(path) + 2; |
932 | + char *dev; |
933 | + int rval = -1; |
934 | + |
935 | + if ((dev = malloc(devl)) == NULL) { |
936 | + printf("nfsMount: out of memory\n"); |
937 | + return -1; |
938 | + } |
939 | + sprintf(dev, "%s:%s", uidhost, path); |
940 | + rval = mount_and_make_target_path ( |
941 | + dev, mntpoint, RTEMS_FILESYSTEM_TYPE_NFS, |
942 | + RTEMS_FILESYSTEM_READ_WRITE, NULL ); |
943 | + if(rval) |
944 | + perror("mount failed"); |
945 | + |
946 | + free(dev); |
947 | + return rval; |
948 | +} |
949 | +#define NFS_INIT |
950 | +#endif |
951 | + |
952 | +static void |
953 | +initialize_remote_filesystem(char **argv, int hasLocalFilesystem) |
954 | +{ |
955 | +#ifndef OMIT_NFS_SUPPORT |
956 | + char *server_name = "notDefined"; |
957 | + char *server_path = "notDefined"; |
958 | + char *mount_point = "notDefined"; |
959 | + char *cp; |
960 | + int l = 0; |
961 | +#endif |
962 | + |
963 | + printf ("***** Initializing TFTP *****\n"); |
964 | + if(mount_and_make_target_path("BOOTP_HOST:/", |
965 | + "/TFTP/BOOTP_HOST", |
966 | + RTEMS_FILESYSTEM_TYPE_TFTPFS, |
967 | + RTEMS_FILESYSTEM_READ_WRITE, |
968 | + NULL)) { |
969 | + perror("mount TFTP"); |
970 | + } |
971 | + |
972 | + if(rtems_bsdnet_bootp_cmdline && strncmp("/TFTP", rtems_bsdnet_bootp_cmdline, 4)==0) { |
973 | + argv[1] = rtems_bsdnet_bootp_cmdline; |
974 | + printf("Boot from TFTP\n"); |
975 | + return; |
976 | + } |
977 | + |
978 | + printf ("***** Initializing NFS *****\n"); |
979 | + NFS_INIT |
980 | + if (env_nfsServer && env_nfsPath && env_nfsMountPoint) { |
981 | + server_name = env_nfsServer; |
982 | + server_path = env_nfsPath; |
983 | + mount_point = env_nfsMountPoint; |
984 | + cp = mount_point; |
985 | + while ((cp = strchr(cp+1, '/')) != NULL) { |
986 | + *cp = '\0'; |
987 | + if ((mkdir (mount_point, 0755) != 0) |
988 | + && (errno != EEXIST)) |
989 | + LogFatal("Can't create directory \"%s\": %s.\n", |
990 | + mount_point, strerror(errno)); |
991 | + *cp = '/'; |
992 | + } |
993 | + argv[1] = rtems_bsdnet_bootp_cmdline; |
994 | + } |
995 | + else if (hasLocalFilesystem) { |
996 | + printf("Using Local FS\n"); |
997 | + return; |
998 | + } |
999 | + else if (rtems_bsdnet_bootp_cmdline) { |
1000 | + /* |
1001 | + * Use first component of nvram/bootp command line pathname |
1002 | + * to set up initial NFS mount. A "/tftpboot/" is prepended |
1003 | + * if the pathname does not begin with a '/'. This allows |
1004 | + * NFS and TFTP to have a similar view of the remote system. |
1005 | + */ |
1006 | + if (rtems_bsdnet_bootp_cmdline[0] == '/') |
1007 | + cp = rtems_bsdnet_bootp_cmdline + 1; |
1008 | + else |
1009 | + cp = rtems_bsdnet_bootp_cmdline; |
1010 | + cp = strchr(cp, '/'); |
1011 | + if ((cp == NULL) |
1012 | + || ((l = cp - rtems_bsdnet_bootp_cmdline) == 0)) |
1013 | + LogFatal("\"%s\" is not a valid command pathname.\n", rtems_bsdnet_bootp_cmdline); |
1014 | + cp = mustMalloc(l + 20, "NFS mount paths"); |
1015 | + server_path = cp; |
1016 | + server_name = rtems_bsdnet_bootp_server_name; |
1017 | + if (rtems_bsdnet_bootp_cmdline[0] == '/') { |
1018 | + mount_point = server_path; |
1019 | + strncpy(mount_point, rtems_bsdnet_bootp_cmdline, l); |
1020 | + mount_point[l] = '\0'; |
1021 | + argv[1] = rtems_bsdnet_bootp_cmdline; |
1022 | + /* |
1023 | + * Its probably common to embed the mount point in the server |
1024 | + * name so, when this is occurring, dont clobber the mount point |
1025 | + * by appending the first node from the command path. This allows |
1026 | + * the mount point to be a different path then the server's mount |
1027 | + * path. |
1028 | + * |
1029 | + * This allows for example a line similar to as follows the DHCP |
1030 | + * configuration file. |
1031 | + * |
1032 | + * server-name "159.233@192.168.0.123:/vol/vol0/bootRTEMS"; |
1033 | + */ |
1034 | + if ( server_name ) { |
1035 | + const size_t allocSize = strlen ( server_name ) + 2; |
1036 | + char * const pServerName = mustMalloc( allocSize, |
1037 | + "NFS mount paths"); |
1038 | + char * const pServerPath = mustMalloc ( allocSize, |
1039 | + "NFS mount paths"); |
1040 | + const int scanfStatus = sscanf ( |
1041 | + server_name, |
1042 | + "%[^:] : / %s", |
1043 | + pServerName, |
1044 | + pServerPath + 1u ); |
1045 | + |
1046 | + if ( scanfStatus == 2 ) { |
1047 | + pServerPath[0u]= '/'; |
1048 | + server_name = pServerName; |
1049 | + server_path = mount_point = pServerPath; |
1050 | + } |
1051 | + else { |
1052 | + free ( pServerName ); |
1053 | + free ( pServerPath ); |
1054 | + } |
1055 | + } |
1056 | + } |
1057 | + else { |
1058 | + char *abspath = mustMalloc(strlen(rtems_bsdnet_bootp_cmdline)+2,"Absolute command path"); |
1059 | + strcpy(server_path, "/tftpboot/"); |
1060 | + mount_point = server_path + strlen(server_path); |
1061 | + strncpy(mount_point, rtems_bsdnet_bootp_cmdline, l); |
1062 | + mount_point[l] = '\0'; |
1063 | + mount_point--; |
1064 | + strcpy(abspath, "/"); |
1065 | + strcat(abspath, rtems_bsdnet_bootp_cmdline); |
1066 | + argv[1] = abspath; |
1067 | + } |
1068 | + } |
1069 | + if(server_name && server_path && mount_point) { |
1070 | + int ret = nfsMount(server_name, server_path, mount_point); |
1071 | + printf("nfsMount(\"%s\", \"%s\", \"%s\") -> %d\n", server_name, server_path, mount_point, ret); |
1072 | + |
1073 | + } else if (!hasLocalFilesystem) { |
1074 | + char *path; |
1075 | + int pathsize = 200; |
1076 | + int l; |
1077 | + |
1078 | + printf("No NFS configuration found. Falling back to TFTP\n"); |
1079 | + |
1080 | + path = mustMalloc(pathsize, "Command path name "); |
1081 | + strcpy (path, "/TFTP/BOOTP_HOST/epics/"); |
1082 | + l = strlen (path); |
1083 | + if (gethostname (&path[l], pathsize - l - 10) || (path[l] == '\0')) |
1084 | + { |
1085 | + LogFatal ("Can't get host name"); |
1086 | + } |
1087 | + strcat (path, "/st.cmd"); |
1088 | + argv[1] = path; |
1089 | + |
1090 | + } else { |
1091 | + printf("Local FS\n"); |
1092 | + } |
1093 | +} |
1094 | + |
1095 | +static |
1096 | +char rtems_etc_hosts[] = "127.0.0.1 localhost\n"; |
1097 | + |
1098 | +/* If it doesn't already exist, create /etc/hosts with an entry for 'localhost' */ |
1099 | +static |
1100 | +void fixup_hosts(void) |
1101 | +{ |
1102 | + FILE *fp; |
1103 | + int ret; |
1104 | + struct stat STAT; |
1105 | + |
1106 | + ret=stat("/etc/hosts", &STAT); |
1107 | + if(ret==0) |
1108 | + { |
1109 | + return; /* already exists, assume file */ |
1110 | + } else if(errno!=ENOENT) { |
1111 | + perror("error: fixup_hosts stat /etc/hosts"); |
1112 | + return; |
1113 | + } |
1114 | + ret = mkdir("/etc", 0775); |
1115 | + if(ret!=0 && errno!=EEXIST) |
1116 | + { |
1117 | + perror("error: fixup_hosts create /etc"); |
1118 | + return; |
1119 | + } |
1120 | + |
1121 | + if((fp=fopen("/etc/hosts", "w"))==NULL) |
1122 | + { |
1123 | + perror("error: fixup_hosts create /etc/hosts"); |
1124 | + } |
1125 | + |
1126 | + if(fwrite(rtems_etc_hosts, 1, sizeof(rtems_etc_hosts)-1, fp)!=sizeof(rtems_etc_hosts)-1) |
1127 | + { |
1128 | + perror("error: failed to write /etc/hosts"); |
1129 | + } |
1130 | + fclose(fp); |
1131 | +} |
1132 | + |
1133 | +/* |
1134 | + * Get to the startup script directory |
1135 | + * The TFTP filesystem requires a trailing '/' on chdir arguments. |
1136 | + */ |
1137 | +static void |
1138 | +set_directory (const char *commandline) |
1139 | +{ |
1140 | + const char *cp; |
1141 | + char *directoryPath; |
1142 | + int l; |
1143 | + |
1144 | + cp = strrchr(commandline, '/'); |
1145 | + if (cp == NULL) { |
1146 | + l = 0; |
1147 | + cp = "/"; |
1148 | + } |
1149 | + else { |
1150 | + l = cp - commandline; |
1151 | + cp = commandline; |
1152 | + } |
1153 | + directoryPath = mustMalloc(l + 2, "Command path directory "); |
1154 | + strncpy(directoryPath, cp, l); |
1155 | + directoryPath[l] = '/'; |
1156 | + directoryPath[l+1] = '\0'; |
1157 | + if (chdir (directoryPath) < 0) |
1158 | + LogFatal ("Can't set initial directory(%s): %s\n", directoryPath, strerror(errno)); |
1159 | + else |
1160 | + free(directoryPath); |
1161 | +} |
1162 | + |
1163 | +/* |
1164 | + *********************************************************************** |
1165 | + * RTEMS/EPICS COMMANDS * |
1166 | + *********************************************************************** |
1167 | + */ |
1168 | +/* |
1169 | + * RTEMS status |
1170 | + */ |
1171 | +static void |
1172 | +rtems_netstat (unsigned int level) |
1173 | +{ |
1174 | + rtems_bsdnet_show_if_stats (); |
1175 | + rtems_bsdnet_show_mbuf_stats (); |
1176 | + if (level >= 1) { |
1177 | + rtems_bsdnet_show_inet_routes (); |
1178 | + } |
1179 | + if (level >= 2) { |
1180 | + rtems_bsdnet_show_ip_stats (); |
1181 | + rtems_bsdnet_show_icmp_stats (); |
1182 | + rtems_bsdnet_show_udp_stats (); |
1183 | + rtems_bsdnet_show_tcp_stats (); |
1184 | + } |
1185 | +} |
1186 | + |
1187 | +static const iocshArg netStatArg0 = { "level",iocshArgInt}; |
1188 | +static const iocshArg * const netStatArgs[1] = {&netStatArg0}; |
1189 | +static const iocshFuncDef netStatFuncDef = {"netstat",1,netStatArgs}; |
1190 | +static void netStatCallFunc(const iocshArgBuf *args) |
1191 | +{ |
1192 | + rtems_netstat(args[0].ival); |
1193 | +} |
1194 | + |
1195 | +static const iocshFuncDef heapSpaceFuncDef = {"heapSpace",0,NULL}; |
1196 | +static void heapSpaceCallFunc(const iocshArgBuf *args) |
1197 | +{ |
1198 | + Heap_Information_block info; |
1199 | + double x; |
1200 | + |
1201 | + malloc_info (&info); |
1202 | + x = info.Stats.size - (unsigned long) |
1203 | + (info.Stats.lifetime_allocated - info.Stats.lifetime_freed); |
1204 | + if (x >= 1024*1024) |
1205 | + printf("Heap space: %.1f MB\n", x / (1024 * 1024)); |
1206 | + else |
1207 | + printf("Heap space: %.1f kB\n", x / 1024); |
1208 | +} |
1209 | + |
1210 | +#ifndef OMIT_NFS_SUPPORT |
1211 | +static const iocshArg nfsMountArg0 = { "[uid.gid@]host",iocshArgString}; |
1212 | +static const iocshArg nfsMountArg1 = { "server path",iocshArgString}; |
1213 | +static const iocshArg nfsMountArg2 = { "mount point",iocshArgString}; |
1214 | +static const iocshArg * const nfsMountArgs[3] = {&nfsMountArg0,&nfsMountArg1, |
1215 | + &nfsMountArg2}; |
1216 | +static const iocshFuncDef nfsMountFuncDef = {"nfsMount",3,nfsMountArgs}; |
1217 | +static void nfsMountCallFunc(const iocshArgBuf *args) |
1218 | +{ |
1219 | + char *cp = args[2].sval; |
1220 | + while ((cp = strchr(cp+1, '/')) != NULL) { |
1221 | + *cp = '\0'; |
1222 | + if ((mkdir (args[2].sval, 0755) != 0) && (errno != EEXIST)) { |
1223 | + printf("Can't create directory \"%s\": %s.\n", |
1224 | + args[2].sval, strerror(errno)); |
1225 | + return; |
1226 | + } |
1227 | + *cp = '/'; |
1228 | + } |
1229 | + nfsMount(args[0].sval, args[1].sval, args[2].sval); |
1230 | +} |
1231 | +#endif |
1232 | + |
1233 | +#ifdef USE_GDBSTUB |
1234 | +static const iocshArg gdbstartArg0 = { "prio",iocshArgInt}; |
1235 | +static const iocshArg gdbstartArg1 = { "ttyName",iocshArgString}; |
1236 | +static const iocshArg * const gdbstartArgs[3] = {&gdbstartArg0,&gdbstartArg1}; |
1237 | +static const iocshFuncDef gdbstartFuncDef = {"rtems_gdb_start",2,gdbstartArgs}; |
1238 | +static void gdbstartCallFunc(const iocshArgBuf *args) |
1239 | +{ |
1240 | + rtems_gdb_start(args[0].ival, args->sval); |
1241 | +} |
1242 | + |
1243 | +static const iocshArg gdbstopArg0 = { "override",iocshArgInt}; |
1244 | +static const iocshArg * const gdbstopArgs[3] = {&gdbstopArg0}; |
1245 | +static const iocshFuncDef gdbstopFuncDef = {"rtems_gdb_stop",1,gdbstopArgs}; |
1246 | +static void gdbstopCallFunc(const iocshArgBuf *args) |
1247 | +{ |
1248 | + rtems_gdb_stop(args[0].ival); |
1249 | +} |
1250 | +#endif /* USE_GDBSTUB */ |
1251 | + |
1252 | +/* |
1253 | + * Register RTEMS-specific commands |
1254 | + */ |
1255 | +static void iocshRegisterRTEMS (void) |
1256 | +{ |
1257 | + iocshRegister(&netStatFuncDef, netStatCallFunc); |
1258 | + iocshRegister(&heapSpaceFuncDef, heapSpaceCallFunc); |
1259 | +#ifndef OMIT_NFS_SUPPORT |
1260 | + iocshRegister(&nfsMountFuncDef, nfsMountCallFunc); |
1261 | +#endif |
1262 | +#ifdef USE_GDBSTUB |
1263 | + iocshRegister(&gdbstartFuncDef, gdbstartCallFunc); |
1264 | + iocshRegister(&gdbstopFuncDef, gdbstopCallFunc); |
1265 | +#endif |
1266 | +} |
1267 | + |
1268 | +/* |
1269 | + * Set up the console serial line (no handshaking) |
1270 | + */ |
1271 | +static void |
1272 | +initConsole (void) |
1273 | +{ |
1274 | + struct termios t; |
1275 | + |
1276 | + if (tcgetattr (fileno (stdin), &t) < 0) { |
1277 | + printf ("tcgetattr failed: %s\n", strerror (errno)); |
1278 | + return; |
1279 | + } |
1280 | + t.c_iflag &= ~(IXOFF | IXON | IXANY); |
1281 | + if (tcsetattr (fileno (stdin), TCSANOW, &t) < 0) { |
1282 | + printf ("tcsetattr failed: %s\n", strerror (errno)); |
1283 | + return; |
1284 | + } |
1285 | +} |
1286 | + |
1287 | +/* |
1288 | + * Hook to ensure that BSP cleanup code gets run on exit |
1289 | + */ |
1290 | +static void |
1291 | +exitHandler(void) |
1292 | +{ |
1293 | + rtems_shutdown_executive(0); |
1294 | +} |
1295 | + |
1296 | +extern char *env_rtems_gdb_stub; |
1297 | +extern int epics_initialized_environment; |
1298 | +extern void setBootConfigFromNVRAM(void); |
1299 | +extern void bootpFallbackFromNVRAM(void); |
1300 | + |
1301 | +static void * |
1302 | +rtemsEpicsStartUp(void *arg) |
1303 | +{ |
1304 | + int result; |
1305 | + char *argv[3] = { NULL, NULL, NULL }; |
1306 | + char *cp; |
1307 | + rtems_status_code sc; |
1308 | + rtems_time_of_day now; |
1309 | + |
1310 | + /* |
1311 | + * Explain why we're here, calls errlogPrintf -> epicsThreadInit etc. |
1312 | + */ |
1313 | + |
1314 | + errlogSetConsole(stdout); // prevent mixup of stdout/stderr |
1315 | + logReset(); |
1316 | + |
1317 | + /* |
1318 | + * Architecture-specific hooks |
1319 | + */ |
1320 | + if (epicsRtemsInitPreSetBootConfigFromNVRAM(&rtems_bsdnet_config) != 0) |
1321 | + delayedPanic("epicsRtemsInitPreSetBootConfigFromNVRAM"); |
1322 | + epics_initialized_environment = 0; |
1323 | + setBootConfigFromNVRAM(); |
1324 | + if (epicsRtemsInitPostSetBootConfigFromNVRAM(&rtems_bsdnet_config) != 0) |
1325 | + delayedPanic("epicsRtemsInitPostSetBootConfigFromNVRAM"); |
1326 | + |
1327 | + /* |
1328 | + * Create a reasonable environment |
1329 | + */ |
1330 | + initConsole (); |
1331 | + putenv ("TERM=xterm"); |
1332 | + putenv ("IOCSH_HISTSIZE=20"); |
1333 | + |
1334 | + if(!epics_initialized_environment) { |
1335 | + fprintf(stdout, "BSP doesn't implement non-volatile memory.\n"); |
1336 | + } |
1337 | + |
1338 | + /* |
1339 | + * Display some OS information |
1340 | + */ |
1341 | + printf("\n***** RTEMS Version: %s *****\n", |
1342 | + rtems_get_version_string()); |
1343 | + |
1344 | + /* |
1345 | + * Start network |
1346 | + */ |
1347 | + if ((cp = getenv("EPICS_TS_NTP_INET")) != NULL) |
1348 | + rtems_bsdnet_config.ntp_server[0] = cp; |
1349 | + if (rtems_bsdnet_config.network_task_priority == 0) |
1350 | + { |
1351 | + unsigned int p; |
1352 | + if (epicsThreadHighestPriorityLevelBelow(epicsThreadPriorityScanLow, &p) |
1353 | + == epicsThreadBooleanStatusSuccess) |
1354 | + { |
1355 | + |
1356 | + /* This is an rtems task, so use the rtems task priority */ |
1357 | + rtems_bsdnet_config.network_task_priority = |
1358 | + epicsThreadGetPosixMinPriorityValue() + epicsThreadGetPosixPriorityValue(p); |
1359 | + /* For rtems tasks, lower number = higher priority */ |
1360 | + |
1361 | + } |
1362 | + } |
1363 | + printf("\n***** Initializing network *****\n"); |
1364 | + rtems_bsdnet_initialize_network(); |
1365 | + bootpFallbackFromNVRAM(); |
1366 | + printf("\n***** Setting up file system *****\n"); |
1367 | + initialize_remote_filesystem(argv, initialize_local_filesystem(argv)); |
1368 | + fixup_hosts(); |
1369 | + |
1370 | + if(env_rtems_gdb_stub) { |
1371 | +#ifdef USE_GDBSTUB |
1372 | + char *arg = NULL; |
1373 | + if(strcmp(env_rtems_gdb_stub, "yes")!=0) |
1374 | + arg = env_rtems_gdb_stub; |
1375 | + printf("Start GDB server on %s\n", arg); |
1376 | + rtems_gdb_start(0,arg); |
1377 | +#else |
1378 | + printf("GDB server support not enabled.\n"); |
1379 | +#endif |
1380 | + } |
1381 | + /* |
1382 | + * More environment: iocsh prompt and hostname |
1383 | + */ |
1384 | + { |
1385 | + char hostname[1024]; |
1386 | + gethostname(hostname, 1023); |
1387 | + char *cp = mustMalloc(strlen(hostname)+3, "iocsh prompt"); |
1388 | + sprintf(cp, "%s> ", hostname); |
1389 | + epicsEnvSet ("IOCSH_PS1", cp); |
1390 | + epicsEnvSet("IOC_NAME", hostname); |
1391 | + } |
1392 | + |
1393 | + /* |
1394 | + * Use BSP-supplied time of day if available otherwise supply default time. |
1395 | + * It is very likely that other time synchronization facilities in EPICS |
1396 | + * will soon override this value. |
1397 | + */ |
1398 | + if (rtems_clock_get_tod(&now) != RTEMS_SUCCESSFUL) { |
1399 | + now.year = 2012; |
1400 | + now.month = 4; |
1401 | + now.day = 14; |
1402 | + now.hour = 7; |
1403 | + now.minute = 23; |
1404 | + now.second = 0; |
1405 | + now.ticks = 0; |
1406 | + if ((sc = rtems_clock_set (&now)) != RTEMS_SUCCESSFUL) |
1407 | + printf ("***** Can't set time: %s\n", rtems_status_text (sc)); |
1408 | + } |
1409 | + if (getenv("TZ") == NULL) { |
1410 | + const char *tzp = envGetConfigParamPtr(&EPICS_TIMEZONE); |
1411 | + if (tzp == NULL) { |
1412 | + printf("Warning -- no timezone information available -- times will be displayed as GMT.\n"); |
1413 | + } |
1414 | + else { |
1415 | + char tz[10]; |
1416 | + int minWest, toDst = 0, fromDst = 0; |
1417 | + if(sscanf(tzp, "%9[^:]::%d:%d:%d", tz, &minWest, &toDst, &fromDst) < 2) { |
1418 | + printf("Warning: EPICS_TIMEZONE (%s) unrecognizable -- times will be displayed as GMT.\n", tzp); |
1419 | + } |
1420 | + else { |
1421 | + char posixTzBuf[40]; |
1422 | + char *p = posixTzBuf; |
1423 | + p += sprintf(p, "%cST%d:%.2d", tz[0], minWest/60, minWest%60); |
1424 | + if (toDst != fromDst) |
1425 | + p += sprintf(p, "%cDT", tz[0]); |
1426 | + epicsEnvSet("TZ", posixTzBuf); |
1427 | + } |
1428 | + } |
1429 | + } |
1430 | + tzset(); |
1431 | + /* osdTimeRegister() was called during C++ initialization */ |
1432 | + rtems_netstat(0); |
1433 | + /* |
1434 | + * Run the EPICS startup script |
1435 | + */ |
1436 | + printf ("***** Preparing EPICS application *****\n"); |
1437 | + iocshRegisterRTEMS (); |
1438 | + set_directory (argv[1]); |
1439 | + epicsEnvSet ("IOC_STARTUP_SCRIPT", argv[1]); |
1440 | + atexit(exitHandler); |
1441 | + errlogFlush(); |
1442 | + printf ("***** Starting EPICS application *****\n"); |
1443 | + result = main ((sizeof argv / sizeof argv[0]) - 1, argv); |
1444 | + printf ("***** IOC application terminating *****\n"); |
1445 | + epicsThreadSleep(1.0); |
1446 | + epicsExit(result); |
1447 | + return NULL; |
1448 | +} |
1449 | + |
1450 | +/* |
1451 | + * RTEMS Startup task |
1452 | + */ |
1453 | +void * |
1454 | +POSIX_Init (void *argument) |
1455 | +{ |
1456 | + struct sched_param schedParam; |
1457 | + /* |
1458 | + * Override RTEMS Posix configuration, starts with posix prio 2 |
1459 | + */ |
1460 | + |
1461 | + double maxPriority,minPriority,slope,posixPrio; |
1462 | + maxPriority = (double)sched_get_priority_max(SCHED_FIFO); |
1463 | + minPriority = (double)sched_get_priority_min(SCHED_FIFO); |
1464 | + slope = (maxPriority - minPriority)/100.0; |
1465 | + posixPrio = (double)epicsThreadPriorityIocsh * slope + minPriority; |
1466 | + schedParam.sched_priority = (int) posixPrio; |
1467 | + int s = pthread_setschedparam(pthread_self(), SCHED_FIFO, &schedParam); |
1468 | + if(s) delayedPanic ("Panix pthread_attr_setschedparam in Init ..."); |
1469 | + |
1470 | + rtemsMainInit(epicsThreadPriorityIocsh); |
1471 | + /* try to retrieve pthreadInfo from global list for _main_ */ |
1472 | + rtemsEpicsStartUp(NULL); |
1473 | + return 0; |
1474 | +} |
1475 | + |
1476 | +#if defined(QEMU_FIXUPS) |
1477 | +/* Override some hooks (weak symbols) |
1478 | + * if BSP defaults aren't configured for running tests. |
1479 | + */ |
1480 | + |
1481 | + |
1482 | +/* Ensure that stdio goes to serial (so it can be captured) */ |
1483 | +#if defined(__i386__) && !USE_COM1_AS_CONSOLE |
1484 | +#include <uart.h> |
1485 | +extern int BSPPrintkPort; |
1486 | +void bsp_predriver_hook(void) |
1487 | +{ |
1488 | + BSPConsolePort = BSP_CONSOLE_PORT_COM1; |
1489 | + BSPPrintkPort = BSP_CONSOLE_PORT_COM1; |
1490 | +} |
1491 | +#endif |
1492 | + |
1493 | +/* reboot immediately when done. */ |
1494 | +#if defined(__i386__) && BSP_PRESS_KEY_FOR_RESET |
1495 | +void bsp_cleanup(void) |
1496 | +{ |
1497 | + void bsp_reset(); |
1498 | + bsp_reset(); |
1499 | +} |
1500 | +#endif |
1501 | + |
1502 | +#endif /* QEMU_FIXUPS */ |
1503 | + |
1504 | +int cexpdebug __attribute__((weak)); |
1505 | diff --git a/RTEMS/posix/rtems_netconfig.c b/RTEMS/posix/rtems_netconfig.c |
1506 | new file mode 100644 |
1507 | index 0000000..86ed527 |
1508 | --- /dev/null |
1509 | +++ b/RTEMS/posix/rtems_netconfig.c |
1510 | @@ -0,0 +1,128 @@ |
1511 | +/*************************************************************************\ |
1512 | +* Copyright (c) 2002 The University of Saskatchewan |
1513 | +* Copyright (c) 2017 Fritz-Haber-Institut der Max-Planck-Gesellschaft |
1514 | +* EPICS BASE is distributed subject to a Software License Agreement found |
1515 | +* in file LICENSE that is included with this distribution. |
1516 | +\*************************************************************************/ |
1517 | +/* |
1518 | + * RTEMS network configuration for EPICS |
1519 | + * Author: W. Eric Norum |
1520 | + * Heinz Junkes |
1521 | + * |
1522 | + * Version for RTEMS-5 |
1523 | + * |
1524 | + * This file can be copied to an application source dirctory |
1525 | + * and modified to override the values shown below. |
1526 | + */ |
1527 | +#include <stdio.h> |
1528 | +#include <bsp.h> |
1529 | +#include <rtems/rtems_bsdnet.h> |
1530 | + |
1531 | +#include "rtems_netconfig.h" |
1532 | + |
1533 | +#define stringOf(x) #x |
1534 | +#define STRING(x) stringOf(x) |
1535 | + |
1536 | +/* |
1537 | + * The following configures up to 2 network interface card(s) using |
1538 | + * settings in either configure/os/CONFIG_SITE.Common.RTEMS or in a |
1539 | + * BSP-specific configure/os/CONFIG_SITE.Common.RTEMS-<bsp> file. |
1540 | + * If no settings are provided, it uses the BSP's defaults instead. |
1541 | + */ |
1542 | + |
1543 | +#if defined(RTEMS_NETWORK_DRIVER_NAME_1) |
1544 | + |
1545 | + #if defined(RTEMS_NETWORK_DRIVER_NAME_2) |
1546 | + static struct rtems_bsdnet_ifconfig netdriver_config_2 = { |
1547 | + STRING(RTEMS_NETWORK_DRIVER_NAME_2), |
1548 | + #if defined(RTEMS_NETWORK_DRIVER_ATTACH_2) |
1549 | + RTEMS_NETWORK_DRIVER_ATTACH_2, /* specific attach function */ |
1550 | + #else |
1551 | + RTEMS_BSP_NETWORK_DRIVER_ATTACH, /* default attach function */ |
1552 | + #endif |
1553 | + NULL, /* last interface */ |
1554 | + #if defined(RTEMS_NETWORK_IP4_ADDR_2) |
1555 | + STRING(RTEMS_NETWORK_IP4_ADDR_2), |
1556 | + #if defined(RTEMS_NETWORK_IP4_MASK_2) |
1557 | + STRING(RTEMS_NETWORK_IP4_MASK_2), |
1558 | + #endif |
1559 | + #endif |
1560 | + }; |
1561 | + #endif /* RTEMS_NETWORK_DRIVER_NAME_2 */ |
1562 | + |
1563 | + static struct rtems_bsdnet_ifconfig netdriver_config = { |
1564 | + STRING(RTEMS_NETWORK_DRIVER_NAME_1), |
1565 | + #if defined(RTEMS_NETWORK_DRIVER_ATTACH_1) |
1566 | + RTEMS_NETWORK_DRIVER_ATTACH_1, /* specific attach function */ |
1567 | + #else |
1568 | + RTEMS_BSP_NETWORK_DRIVER_ATTACH, /* default attach function */ |
1569 | + #endif |
1570 | + #if defined(RTEMS_NETWORK_DRIVER_NAME_2) |
1571 | + &netdriver_config_2, /* link to next interface */ |
1572 | + #else |
1573 | + NULL, /* last interface */ |
1574 | + #endif |
1575 | + #if defined(RTEMS_NETWORK_IP4_ADDR_1) |
1576 | + STRING(RTEMS_NETWORK_IP4_ADDR_1), |
1577 | + #if defined(RTEMS_NETWORK_IP4_MASK_1) |
1578 | + STRING(RTEMS_NETWORK_IP4_MASK_1), |
1579 | + #endif |
1580 | + #endif |
1581 | + }; |
1582 | + #define FIRST_DRIVER_CONFIG &netdriver_config |
1583 | + |
1584 | +#else /* RTEMS_NETWORK_DRIVER_NAME_1 */ |
1585 | + |
1586 | +/* Use the BSP-provided standard macros */ |
1587 | +static struct rtems_bsdnet_ifconfig bsp_driver_config = { |
1588 | + RTEMS_BSP_NETWORK_DRIVER_NAME, /* name */ |
1589 | + RTEMS_BSP_NETWORK_DRIVER_ATTACH, /* attach function */ |
1590 | + NULL, /* last interface */ |
1591 | +}; |
1592 | +#define FIRST_DRIVER_CONFIG &bsp_driver_config |
1593 | + |
1594 | +#endif |
1595 | + |
1596 | +/* |
1597 | + * Allow configure/os/CONFIG_SITE.Common.RTEMS to provide domain name |
1598 | + */ |
1599 | +#ifdef RTEMS_NETWORK_CONFIG_DNS_DOMAINNAME |
1600 | +# define MY_DOMAINNAME STRING(RTEMS_NETWORK_CONFIG_DNS_DOMAINNAME) |
1601 | +#else |
1602 | +# define MY_DOMAINNAME NULL |
1603 | +#endif |
1604 | + |
1605 | +/* |
1606 | + * Allow non-BOOTP network configuration |
1607 | + */ |
1608 | +#ifndef MY_DO_BOOTP |
1609 | +# define MY_DO_BOOTP rtems_bsdnet_do_bootp |
1610 | +#endif |
1611 | + |
1612 | +/* |
1613 | + * Allow site- and BSP-specific network buffer space configuration. |
1614 | + * The macro values are specified in KBytes. |
1615 | + */ |
1616 | +#ifndef RTEMS_NETWORK_CONFIG_MBUF_SPACE |
1617 | +# define RTEMS_NETWORK_CONFIG_MBUF_SPACE 180 |
1618 | +#endif |
1619 | +#ifndef RTEMS_NETWORK_CONFIG_CLUSTER_SPACE |
1620 | +# define RTEMS_NETWORK_CONFIG_CLUSTER_SPACE 350 |
1621 | +#endif |
1622 | + |
1623 | +/* |
1624 | + * Network configuration |
1625 | + */ |
1626 | +struct rtems_bsdnet_config rtems_bsdnet_config = { |
1627 | + FIRST_DRIVER_CONFIG, /* Link to next interface */ |
1628 | + MY_DO_BOOTP, /* How to find network config */ |
1629 | + 0, /* If 0 then the network daemons will run at a */ |
1630 | + /* priority just less than the lowest-priority */ |
1631 | + /* EPICS scan thread. */ |
1632 | + /* If non-zero then the network daemons will run */ |
1633 | + /* at this *RTEMS* priority */ |
1634 | + RTEMS_NETWORK_CONFIG_MBUF_SPACE*1024, |
1635 | + RTEMS_NETWORK_CONFIG_CLUSTER_SPACE*1024, |
1636 | + NULL, /* Host name */ |
1637 | + MY_DOMAINNAME, /* Domain name */ |
1638 | +}; |
1639 | diff --git a/RTEMS/posix/setBootConfigFromNVRAM.c b/RTEMS/posix/setBootConfigFromNVRAM.c |
1640 | new file mode 100644 |
1641 | index 0000000..8a93d95 |
1642 | --- /dev/null |
1643 | +++ b/RTEMS/posix/setBootConfigFromNVRAM.c |
1644 | @@ -0,0 +1,458 @@ |
1645 | +/*************************************************************************\ |
1646 | +* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne |
1647 | +* National Laboratory. |
1648 | +* EPICS BASE is distributed subject to a Software License Agreement found |
1649 | +* in file LICENSE that is included with this distribution. |
1650 | +\*************************************************************************/ |
1651 | + |
1652 | +#include <sys/types.h> |
1653 | +#include <sys/socket.h> |
1654 | +#include <arpa/inet.h> |
1655 | +#include <netinet/in.h> |
1656 | +#include <fcntl.h> |
1657 | +#include <unistd.h> |
1658 | +#include <rtems/rtems_bsdnet.h> |
1659 | +#include <bsp.h> |
1660 | +#include <string.h> |
1661 | +#include <ctype.h> |
1662 | +#include <errno.h> |
1663 | +#include <epicsStdlib.h> |
1664 | +#include <epicsStdio.h> |
1665 | +#include <epicsString.h> |
1666 | +#include <envDefs.h> |
1667 | + |
1668 | +#include <osiSock.h> |
1669 | + |
1670 | +char *env_nfsServer; |
1671 | +char *env_nfsPath; |
1672 | +char *env_nfsMountPoint; |
1673 | +int epics_initialized_environment; |
1674 | +char *env_rtems_gdb_stub = NULL; |
1675 | + |
1676 | +/* |
1677 | + * Split argument string of form nfs_server:nfs_export:<path> |
1678 | + * The nfs_export component will be used as: |
1679 | + * - the path to the directory exported from the NFS server |
1680 | + * - the local mount point |
1681 | + * - a prefix of <path> |
1682 | + * For example, the argument string: |
1683 | + * romeo:/export/users:smith/ioc/iocexample/st.cmd |
1684 | + * would: |
1685 | + * - mount /export/users from NFS server romeo on /export/users |
1686 | + * - chdir to /export/users/smith/ioc/iocexample |
1687 | + * - read commands from st.cmd |
1688 | + */ |
1689 | +static void |
1690 | +splitRtemsBsdnetBootpCmdline(void) |
1691 | +{ |
1692 | + char *cp1, *cp2, *cp3; |
1693 | + |
1694 | + if ((cp1 = rtems_bsdnet_bootp_cmdline) == NULL) |
1695 | + return; |
1696 | + if (((cp2 = strchr(cp1, ':')) != NULL) |
1697 | + && (((cp3 = strchr(cp2+1, ' ')) != NULL) |
1698 | + || ((cp3 = strchr(cp2+1, ':')) != NULL))) { |
1699 | + int l1 = cp2 - cp1; |
1700 | + int l2 = cp3 - cp2 - 1; |
1701 | + int l3 = strlen(cp3) - 1; |
1702 | + if (l1 && l2 && l3) { |
1703 | + *cp2++ = '\0'; |
1704 | + *cp3 = '\0'; |
1705 | + env_nfsServer = cp1; |
1706 | + env_nfsMountPoint = env_nfsPath = epicsStrDup(cp2); |
1707 | + *cp3 = '/'; |
1708 | + rtems_bsdnet_bootp_cmdline = cp2; |
1709 | + } |
1710 | + } |
1711 | +} |
1712 | + |
1713 | +/* |
1714 | + * Split NFS mount information of the form nfs_server:host_path:local_path |
1715 | + */ |
1716 | +static void |
1717 | +splitNfsMountPath(char *nfsString) |
1718 | +{ |
1719 | + char *cp2, *cp3; |
1720 | + |
1721 | + if (nfsString == NULL) |
1722 | + return; |
1723 | + if (((cp2 = strchr(nfsString, ':')) != NULL) |
1724 | + && (((cp3 = strchr(cp2+1, ' ')) != NULL) |
1725 | + || ((cp3 = strchr(cp2+1, ':')) != NULL))) { |
1726 | + int l1 = cp2 - nfsString; |
1727 | + int l2 = cp3 - cp2 - 1; |
1728 | + int l3 = strlen(cp3) - 1; |
1729 | + if (l1 && l2 && l3) { |
1730 | + *cp2++ = '\0'; |
1731 | + *cp3++ = '\0'; |
1732 | + env_nfsServer = nfsString; |
1733 | + env_nfsPath = cp2; |
1734 | + env_nfsMountPoint = cp3; |
1735 | + } |
1736 | + } |
1737 | +} |
1738 | + |
1739 | +#if defined(HAVE_MOTLOAD) |
1740 | + |
1741 | +/* |
1742 | + * Motorola MOTLOAD NVRAM Access |
1743 | + */ |
1744 | +static char * |
1745 | +gev(const char *parm, volatile char *nvp) |
1746 | +{ |
1747 | + const char *val; |
1748 | + const char *name; |
1749 | + char *ret; |
1750 | + char c; |
1751 | + |
1752 | + for (;;) { |
1753 | + if (*nvp == '\0') |
1754 | + return NULL; |
1755 | + name = parm; |
1756 | + while ((c = *nvp++) != '\0') { |
1757 | + if ((c == '=') && (*name == '\0')) { |
1758 | + val = (char *)nvp; |
1759 | + while (*nvp++ != '\0') |
1760 | + continue; |
1761 | + ret = malloc(nvp - val); |
1762 | + if (ret == NULL) |
1763 | + return NULL; |
1764 | + strcpy(ret, val); |
1765 | + return ret; |
1766 | + } |
1767 | + if (c != *name++) { |
1768 | + while (*nvp++ != '\0') |
1769 | + continue; |
1770 | + break; |
1771 | + } |
1772 | + } |
1773 | + } |
1774 | +} |
1775 | + |
1776 | +static char * |
1777 | +motScriptParm(const char *mot_script_boot, char parm) |
1778 | +{ |
1779 | + const char *cp; |
1780 | + char *ret; |
1781 | + int l; |
1782 | + |
1783 | + while (*mot_script_boot != '\0') { |
1784 | + if (isspace(*(unsigned char *)mot_script_boot) |
1785 | + && (*(mot_script_boot+1) == '-') |
1786 | + && (*(mot_script_boot+2) == parm)) { |
1787 | + mot_script_boot += 3; |
1788 | + cp = mot_script_boot; |
1789 | + while ((*mot_script_boot != '\0') && |
1790 | + !isspace(*(unsigned char *)mot_script_boot)) |
1791 | + mot_script_boot++; |
1792 | + l = mot_script_boot - cp; |
1793 | + ret = malloc(l+1); |
1794 | + if (ret == NULL) |
1795 | + return NULL; |
1796 | + strncpy(ret, cp, l); |
1797 | + *(ret+l) = '\0'; |
1798 | + return ret; |
1799 | + } |
1800 | + mot_script_boot++; |
1801 | + } |
1802 | + return NULL; |
1803 | +} |
1804 | + |
1805 | +void |
1806 | +setBootConfigFromNVRAM(void) |
1807 | +{ |
1808 | + char *cp; |
1809 | + const char *mot_script_boot; |
1810 | + char *nvp; |
1811 | + |
1812 | + if (rtems_bsdnet_config.bootp != NULL) |
1813 | + return; |
1814 | + |
1815 | +# if defined(BSP_NVRAM_BASE_ADDR) |
1816 | + nvp = (volatile unsigned char *)(BSP_NVRAM_BASE_ADDR+0x70f8); |
1817 | +# elif defined(BSP_I2C_VPD_EEPROM_DEV_NAME) |
1818 | + char gev_buf[3592]; |
1819 | + int fd; |
1820 | + if ((fd = open(BSP_I2C_VPD_EEPROM_DEV_NAME, 0)) < 0) { |
1821 | + printf("Can't open %s: %s\n", BSP_I2C_VPD_EEPROM_DEV_NAME, strerror(errno)); |
1822 | + return; |
1823 | + } |
1824 | + lseek(fd, 0x10f8, SEEK_SET); |
1825 | + if (read(fd, gev_buf, sizeof gev_buf) != sizeof gev_buf) { |
1826 | + printf("Can't read %s: %s\n", BSP_I2C_VPD_EEPROM_DEV_NAME, strerror(errno)); |
1827 | + return; |
1828 | + } |
1829 | + close(fd); |
1830 | + nvp = gev_buf; |
1831 | +# else |
1832 | +# error "No way to read GEV!" |
1833 | +# endif |
1834 | + |
1835 | + mot_script_boot = gev("mot-script-boot", nvp); |
1836 | + if ((rtems_bsdnet_bootp_server_name = gev("mot-/dev/enet0-sipa", nvp)) == NULL) |
1837 | + rtems_bsdnet_bootp_server_name = motScriptParm(mot_script_boot, 's'); |
1838 | + |
1839 | + { |
1840 | + struct sockaddr_in ain; |
1841 | + aToIPAddr(rtems_bsdnet_bootp_server_name, 0, &ain); |
1842 | + rtems_bsdnet_bootp_server_address = ain.sin_addr; |
1843 | + } |
1844 | + |
1845 | + if ((rtems_bsdnet_config.gateway = gev("mot-/dev/enet0-gipa", nvp)) == NULL) |
1846 | + rtems_bsdnet_config.gateway = motScriptParm(mot_script_boot, 'g'); |
1847 | + if ((rtems_bsdnet_config.ifconfig->ip_netmask = gev("mot-/dev/enet0-snma", nvp)) == NULL) |
1848 | + rtems_bsdnet_config.ifconfig->ip_netmask = motScriptParm(mot_script_boot, 'm'); |
1849 | + |
1850 | + rtems_bsdnet_config.name_server[0] = gev("rtems-dns-server", nvp); |
1851 | + if (rtems_bsdnet_config.name_server[0] == NULL) |
1852 | + rtems_bsdnet_config.name_server[0] = rtems_bsdnet_bootp_server_name; |
1853 | + cp = gev("rtems-dns-domainname", nvp); |
1854 | + if (cp) |
1855 | + rtems_bsdnet_config.domainname = cp; |
1856 | + |
1857 | + if ((rtems_bsdnet_config.ifconfig->ip_address = gev("mot-/dev/enet0-cipa", nvp)) == NULL) |
1858 | + rtems_bsdnet_config.ifconfig->ip_address = motScriptParm(mot_script_boot, 'c'); |
1859 | + rtems_bsdnet_config.hostname = gev("rtems-client-name", nvp); |
1860 | + if (rtems_bsdnet_config.hostname == NULL) |
1861 | + rtems_bsdnet_config.hostname = rtems_bsdnet_config.ifconfig->ip_address; |
1862 | + |
1863 | + if ((rtems_bsdnet_bootp_boot_file_name = gev("mot-/dev/enet0-file", nvp)) == NULL) |
1864 | + rtems_bsdnet_bootp_boot_file_name = motScriptParm(mot_script_boot, 'f'); |
1865 | + rtems_bsdnet_bootp_cmdline = gev("epics-script", nvp); |
1866 | + splitRtemsBsdnetBootpCmdline(); |
1867 | + splitNfsMountPath(gev("epics-nfsmount", nvp)); |
1868 | + rtems_bsdnet_config.ntp_server[0] = gev("epics-ntpserver", nvp); |
1869 | + if (rtems_bsdnet_config.ntp_server[0] == NULL) |
1870 | + rtems_bsdnet_config.ntp_server[0] = rtems_bsdnet_bootp_server_name; |
1871 | + if ((cp = gev("epics-tz", nvp)) != NULL) |
1872 | + epicsEnvSet("TZ", cp); |
1873 | + env_rtems_gdb_stub = gev("gdb-start", nvp); |
1874 | + epics_initialized_environment = 1; |
1875 | +} |
1876 | + |
1877 | +#elif defined(HAVE_PPCBUG) |
1878 | +/* |
1879 | + * Motorola PPCBUG NVRAM Access |
1880 | + */ |
1881 | +struct ppcbug_nvram { |
1882 | + uint32_t PacketVersionIdentifier; |
1883 | + uint32_t NodeControlMemoryAddress; |
1884 | + uint32_t BootFileLoadAddress; |
1885 | + uint32_t BootFileExecutionAddress; |
1886 | + uint32_t BootFileExecutionDelay; |
1887 | + uint32_t BootFileLength; |
1888 | + uint32_t BootFileByteOffset; |
1889 | + uint32_t TraceBufferAddress; |
1890 | + uint32_t ClientIPAddress; |
1891 | + uint32_t ServerIPAddress; |
1892 | + uint32_t SubnetIPAddressMask; |
1893 | + uint32_t BroadcastIPAddressMask; |
1894 | + uint32_t GatewayIPAddress; |
1895 | + uint8_t BootpRarpRetry; |
1896 | + uint8_t TftpRarpRetry; |
1897 | + uint8_t BootpRarpControl; |
1898 | + uint8_t UpdateControl; |
1899 | + char BootFilenameString[64]; |
1900 | + char ArgumentFilenameString[64]; |
1901 | +}; |
1902 | + |
1903 | +static char *addr(char *cbuf, uint32_t addr) |
1904 | +{ |
1905 | + struct in_addr a; |
1906 | + if ((a.s_addr = addr) == 0) |
1907 | + return NULL; |
1908 | + return (char *)inet_ntop(AF_INET, &a, cbuf, INET_ADDRSTRLEN); |
1909 | +} |
1910 | + |
1911 | +void |
1912 | +setBootConfigFromNVRAM(void) |
1913 | +{ |
1914 | + static struct ppcbug_nvram nvram; |
1915 | + static char ip_address[INET_ADDRSTRLEN]; |
1916 | + static char ip_netmask[INET_ADDRSTRLEN]; |
1917 | + static char server[INET_ADDRSTRLEN]; |
1918 | + static char gateway[INET_ADDRSTRLEN]; |
1919 | + |
1920 | + if (rtems_bsdnet_config.bootp != NULL) |
1921 | + return; |
1922 | + |
1923 | + /* |
1924 | + * Get network configuation from PPCBUG. |
1925 | + * The 'correct' way to do this would be to issue a .NETCFIG PPCBUG |
1926 | + * system call. Unfortunately it is very difficult to issue such a |
1927 | + * call once RTEMS is up and running so we just copy from the 'known' |
1928 | + * location of the network configuration parameters. |
1929 | + * Care must be taken to access the NVRAM a byte at a time. |
1930 | + */ |
1931 | + |
1932 | +#if defined(NVRAM_INDIRECT) |
1933 | + { |
1934 | + volatile char *addrLo = (volatile char *)0x80000074; |
1935 | + volatile char *addrHi = (volatile char *)0x80000075; |
1936 | + volatile char *data = (volatile char *)0x80000077; |
1937 | + int addr = 0x1000; |
1938 | + char *d = (char *)&nvram; |
1939 | + |
1940 | + while (d < ((char *)&nvram + sizeof nvram)) { |
1941 | + *addrLo = addr & 0xFF; |
1942 | + *addrHi = (addr >> 8) & 0xFF; |
1943 | + *d++ = *data; |
1944 | + addr++; |
1945 | + } |
1946 | + } |
1947 | +#else |
1948 | + { |
1949 | + volatile char *s = (volatile char *)0xFFE81000; |
1950 | + char *d = (char *)&nvram; |
1951 | + |
1952 | + while (d < ((char *)&nvram + sizeof nvram)) |
1953 | + *d++ = *s++; |
1954 | + } |
1955 | +#endif |
1956 | + /* |
1957 | + * Assume that the boot server is also the name, log and ntp server! |
1958 | + */ |
1959 | + rtems_bsdnet_config.name_server[0] = |
1960 | + rtems_bsdnet_config.ntp_server[0] = |
1961 | + rtems_bsdnet_bootp_server_name = addr(server, nvram.ServerIPAddress); |
1962 | + rtems_bsdnet_bootp_server_address.s_addr = nvram.ServerIPAddress; |
1963 | + /* |
1964 | + * Nothing better to use as host name! |
1965 | + */ |
1966 | + rtems_bsdnet_config.ifconfig->ip_address = |
1967 | + rtems_bsdnet_config.hostname = addr(ip_address, nvram.ClientIPAddress); |
1968 | + |
1969 | + rtems_bsdnet_config.gateway = addr(gateway, nvram.GatewayIPAddress); |
1970 | + rtems_bsdnet_config.ifconfig->ip_netmask = addr(ip_netmask, nvram.SubnetIPAddressMask); |
1971 | + |
1972 | + rtems_bsdnet_bootp_boot_file_name = nvram.BootFilenameString; |
1973 | + rtems_bsdnet_bootp_cmdline = nvram.ArgumentFilenameString; |
1974 | + splitRtemsBsdnetBootpCmdline(); |
1975 | + epics_initialized_environment = 1; |
1976 | +} |
1977 | + |
1978 | +#elif defined(__mcf528x__) |
1979 | + |
1980 | +static char * |
1981 | +env(const char *parm, const char *defaultValue) |
1982 | +{ |
1983 | + const char *cp = bsp_getbenv(parm); |
1984 | + |
1985 | + if (!cp) { |
1986 | + if (!defaultValue) |
1987 | + return NULL; |
1988 | + cp = defaultValue; |
1989 | + printf ("%s environment variable missing -- using %s.\n", parm, cp); |
1990 | + } |
1991 | + return epicsStrDup(cp); |
1992 | +} |
1993 | + |
1994 | +void |
1995 | +setBootConfigFromNVRAM(void) |
1996 | +{ |
1997 | + const char *cp1; |
1998 | + |
1999 | + if (rtems_bsdnet_config.bootp != NULL) |
2000 | + return; |
2001 | + rtems_bsdnet_config.gateway = env("GATEWAY", NULL); |
2002 | + rtems_bsdnet_config.ifconfig->ip_netmask = env("NETMASK", "255.255.252.0"); |
2003 | + |
2004 | + rtems_bsdnet_bootp_server_name = env("SERVER", "192.168.0.1"); |
2005 | + rtems_bsdnet_config.name_server[0] = env("NAMESERVER", rtems_bsdnet_bootp_server_name); |
2006 | + rtems_bsdnet_config.ntp_server[0] = env("NTPSERVER", rtems_bsdnet_bootp_server_name); |
2007 | + cp1 = env("DOMAIN", NULL); |
2008 | + if (cp1 != NULL) |
2009 | + rtems_bsdnet_config.domainname = cp1; |
2010 | + rtems_bsdnet_config.hostname = env("HOSTNAME", "iocNobody"); |
2011 | + rtems_bsdnet_config.ifconfig->ip_address = env("IPADDR0", "192.168.0.2"); |
2012 | + rtems_bsdnet_bootp_boot_file_name = env("BOOTFILE", "uC5282App.boot"); |
2013 | + rtems_bsdnet_bootp_cmdline = env("CMDLINE", "epics/iocBoot/iocNobody/st.cmd"); |
2014 | + splitNfsMountPath(env("NFSMOUNT", NULL)); |
2015 | + if ((cp1 = env("TZ", NULL)) != NULL) |
2016 | + epicsEnvSet("TZ", cp1); |
2017 | + env_rtems_gdb_stub = env("GDBSTART", NULL); |
2018 | + epics_initialized_environment = 1; |
2019 | +} |
2020 | + |
2021 | +#elif defined(USE_MULTIBOOT) && (__RTEMS_MAJOR__>4 || (__RTEMS_MAJOR__==4 && __RTEMS_MINOR__>9)) |
2022 | + |
2023 | +/* Try to fill out missing BOOTP/DHCP configuration from the environment */ |
2024 | +void |
2025 | +bootpFallbackFromNVRAM(void) |
2026 | +{ |
2027 | +#define ENV2VAR(ENV, VAR) if(!VAR) {VAR = getenv(ENV);} |
2028 | + ENV2VAR("epics-ip", rtems_bsdnet_config.ifconfig->ip_address); |
2029 | + ENV2VAR("epics-gw", rtems_bsdnet_config.gateway); |
2030 | + ENV2VAR("epics-mask", rtems_bsdnet_config.ifconfig->ip_netmask); |
2031 | + ENV2VAR("epics-dns", rtems_bsdnet_config.name_server[0]); |
2032 | + ENV2VAR("epics-domain", rtems_bsdnet_config.domainname); |
2033 | + ENV2VAR("epics-server", rtems_bsdnet_bootp_server_name); |
2034 | + ENV2VAR("epics-client", rtems_bsdnet_config.hostname); |
2035 | + ENV2VAR("epics-script", rtems_bsdnet_bootp_cmdline); |
2036 | + ENV2VAR("epics-ntp", rtems_bsdnet_config.ntp_server[0]); |
2037 | + ENV2VAR("gdb-start", env_rtems_gdb_stub); |
2038 | +#undef ENV2VAR |
2039 | + |
2040 | + if (rtems_bsdnet_config.ntp_server[0] == NULL) |
2041 | + rtems_bsdnet_config.ntp_server[0] = rtems_bsdnet_bootp_server_name; |
2042 | + |
2043 | + splitRtemsBsdnetBootpCmdline(); |
2044 | + splitNfsMountPath(getenv("epics-nfsmount")); |
2045 | +} |
2046 | + |
2047 | +void |
2048 | +setBootConfigFromNVRAM(void) |
2049 | +{ |
2050 | + const char *mboot = bsp_cmdline(); |
2051 | + size_t blen = strlen(mboot); |
2052 | + char *mboot2; |
2053 | + char *tok, *store, *save; |
2054 | + |
2055 | + store = mboot2 = malloc(blen+1); |
2056 | + if(!mboot2) |
2057 | + return; |
2058 | + strcpy(mboot2, mboot); |
2059 | + |
2060 | + /* Populate environment with multiboot arguments. |
2061 | + * format of multiboot string is a space seperated list of |
2062 | + * sub-strings. eg. |
2063 | + * "progname --arg=one --other=two otherjunk" |
2064 | + */ |
2065 | + |
2066 | + for(;;mboot2=NULL) { |
2067 | + char *val; |
2068 | + /* break up by space */ |
2069 | + tok = strtok_r(mboot2, " ", &save); |
2070 | + if(!tok) |
2071 | + break; |
2072 | + |
2073 | + /* only accept arguments starting with '--' */ |
2074 | + if(tok[0]!='-' || tok[1]!='-') |
2075 | + continue; |
2076 | + tok+=2; |
2077 | + |
2078 | + /* only accept arguments with an assignment */ |
2079 | + val = strchr(tok, '='); |
2080 | + if(!val) |
2081 | + continue; |
2082 | + *val++ = '\0'; |
2083 | + |
2084 | + epicsEnvSet(tok, val); |
2085 | + printk("Set '%s' = '%s'\n", tok, val); |
2086 | + } |
2087 | + |
2088 | + free(store); |
2089 | + |
2090 | + epics_initialized_environment = 1; |
2091 | +} |
2092 | + |
2093 | +#else |
2094 | +/* |
2095 | + * Placeholder for systems without NVRAM |
2096 | + */ |
2097 | +void |
2098 | +setBootConfigFromNVRAM(void) |
2099 | +{ |
2100 | + /* no point in printing here as the console isn't initialized... */ |
2101 | +} |
2102 | +#endif |
2103 | diff --git a/RTEMS/rtems_netconfig.h b/RTEMS/rtems_netconfig.h |
2104 | new file mode 100644 |
2105 | index 0000000..e894f94 |
2106 | --- /dev/null |
2107 | +++ b/RTEMS/rtems_netconfig.h |
2108 | @@ -0,0 +1,7 @@ |
2109 | +#ifndef RTEMS_NETCONF_H |
2110 | +#define RTEMS_NETCONF_H |
2111 | + |
2112 | +extern int |
2113 | +rtems_ne2kpci_driver_attach (struct rtems_bsdnet_ifconfig *config, int attach); |
2114 | + |
2115 | +#endif /* RTEMS_NETCONF_H */ |
2116 | diff --git a/src/osi/os/RTEMS/epicsAtomicOSD.cpp b/src/osi/os/RTEMS-kernel/epicsAtomicOSD.cpp |
2117 | index e69de29..e69de29 100644 |
2118 | --- a/src/osi/os/RTEMS/epicsAtomicOSD.cpp |
2119 | +++ b/src/osi/os/RTEMS-kernel/epicsAtomicOSD.cpp |
2120 | diff --git a/src/osi/os/RTEMS/epicsAtomicOSD.h b/src/osi/os/RTEMS-kernel/epicsAtomicOSD.h |
2121 | index fefd201..fefd201 100644 |
2122 | --- a/src/osi/os/RTEMS/epicsAtomicOSD.h |
2123 | +++ b/src/osi/os/RTEMS-kernel/epicsAtomicOSD.h |
2124 | diff --git a/src/osi/os/RTEMS/osdEvent.c b/src/osi/os/RTEMS-kernel/osdEvent.c |
2125 | index 4554138..4554138 100644 |
2126 | --- a/src/osi/os/RTEMS/osdEvent.c |
2127 | +++ b/src/osi/os/RTEMS-kernel/osdEvent.c |
2128 | diff --git a/src/osi/os/RTEMS/osdEvent.h b/src/osi/os/RTEMS-kernel/osdEvent.h |
2129 | index 6c53aad..6c53aad 100644 |
2130 | --- a/src/osi/os/RTEMS/osdEvent.h |
2131 | +++ b/src/osi/os/RTEMS-kernel/osdEvent.h |
2132 | diff --git a/src/osi/os/RTEMS/osdFindSymbol.c b/src/osi/os/RTEMS-kernel/osdFindSymbol.c |
2133 | index 9e947f9..9e947f9 100644 |
2134 | --- a/src/osi/os/RTEMS/osdFindSymbol.c |
2135 | +++ b/src/osi/os/RTEMS-kernel/osdFindSymbol.c |
2136 | diff --git a/src/osi/os/RTEMS/osdMessageQueue.c b/src/osi/os/RTEMS-kernel/osdMessageQueue.c |
2137 | index a566de6..a566de6 100644 |
2138 | --- a/src/osi/os/RTEMS/osdMessageQueue.c |
2139 | +++ b/src/osi/os/RTEMS-kernel/osdMessageQueue.c |
2140 | diff --git a/src/osi/os/RTEMS/osdMessageQueue.h b/src/osi/os/RTEMS-kernel/osdMessageQueue.h |
2141 | index 0244a1f..0244a1f 100644 |
2142 | --- a/src/osi/os/RTEMS/osdMessageQueue.h |
2143 | +++ b/src/osi/os/RTEMS-kernel/osdMessageQueue.h |
2144 | diff --git a/src/osi/os/RTEMS/osdMutex.c b/src/osi/os/RTEMS-kernel/osdMutex.c |
2145 | index 96fde6e..96fde6e 100644 |
2146 | --- a/src/osi/os/RTEMS/osdMutex.c |
2147 | +++ b/src/osi/os/RTEMS-kernel/osdMutex.c |
2148 | diff --git a/src/osi/os/RTEMS/osdMutex.h b/src/osi/os/RTEMS-kernel/osdMutex.h |
2149 | index 7e2ecc7..7e2ecc7 100644 |
2150 | --- a/src/osi/os/RTEMS/osdMutex.h |
2151 | +++ b/src/osi/os/RTEMS-kernel/osdMutex.h |
2152 | diff --git a/src/osi/os/RTEMS/osdPoolStatus.c b/src/osi/os/RTEMS-kernel/osdPoolStatus.c |
2153 | index b2f4011..b2f4011 100644 |
2154 | --- a/src/osi/os/RTEMS/osdPoolStatus.c |
2155 | +++ b/src/osi/os/RTEMS-kernel/osdPoolStatus.c |
2156 | diff --git a/src/osi/os/RTEMS/osdProcess.c b/src/osi/os/RTEMS-kernel/osdProcess.c |
2157 | index 2768dbb..2768dbb 100644 |
2158 | --- a/src/osi/os/RTEMS/osdProcess.c |
2159 | +++ b/src/osi/os/RTEMS-kernel/osdProcess.c |
2160 | diff --git a/src/osi/os/RTEMS/osdReadline.c b/src/osi/os/RTEMS-kernel/osdReadline.c |
2161 | index 877db53..877db53 100644 |
2162 | --- a/src/osi/os/RTEMS/osdReadline.c |
2163 | +++ b/src/osi/os/RTEMS-kernel/osdReadline.c |
2164 | diff --git a/src/osi/os/RTEMS/osdSignal.cpp b/src/osi/os/RTEMS-kernel/osdSignal.cpp |
2165 | index 08dfa02..08dfa02 100644 |
2166 | --- a/src/osi/os/RTEMS/osdSignal.cpp |
2167 | +++ b/src/osi/os/RTEMS-kernel/osdSignal.cpp |
2168 | diff --git a/src/osi/os/RTEMS/osdSock.h b/src/osi/os/RTEMS-kernel/osdSock.h |
2169 | index 6177c30..6177c30 100644 |
2170 | --- a/src/osi/os/RTEMS/osdSock.h |
2171 | +++ b/src/osi/os/RTEMS-kernel/osdSock.h |
2172 | diff --git a/src/osi/os/RTEMS/osdSpin.c b/src/osi/os/RTEMS-kernel/osdSpin.c |
2173 | index 7a45468..7a45468 100644 |
2174 | --- a/src/osi/os/RTEMS/osdSpin.c |
2175 | +++ b/src/osi/os/RTEMS-kernel/osdSpin.c |
2176 | diff --git a/src/osi/os/RTEMS/osdStrtod.h b/src/osi/os/RTEMS-kernel/osdStrtod.h |
2177 | index 39fda69..39fda69 100644 |
2178 | --- a/src/osi/os/RTEMS/osdStrtod.h |
2179 | +++ b/src/osi/os/RTEMS-kernel/osdStrtod.h |
2180 | diff --git a/src/osi/os/RTEMS/osdThread.c b/src/osi/os/RTEMS-kernel/osdThread.c |
2181 | index 769e958..769e958 100644 |
2182 | --- a/src/osi/os/RTEMS/osdThread.c |
2183 | +++ b/src/osi/os/RTEMS-kernel/osdThread.c |
2184 | diff --git a/src/osi/os/RTEMS/osdThread.h b/src/osi/os/RTEMS-kernel/osdThread.h |
2185 | index 4451f84..4451f84 100644 |
2186 | --- a/src/osi/os/RTEMS/osdThread.h |
2187 | +++ b/src/osi/os/RTEMS-kernel/osdThread.h |
2188 | diff --git a/src/osi/os/RTEMS/osdThreadExtra.c b/src/osi/os/RTEMS-kernel/osdThreadExtra.c |
2189 | index 0a7c7ae..0a7c7ae 100644 |
2190 | --- a/src/osi/os/RTEMS/osdThreadExtra.c |
2191 | +++ b/src/osi/os/RTEMS-kernel/osdThreadExtra.c |
2192 | diff --git a/src/osi/os/RTEMS/osdTime.cpp b/src/osi/os/RTEMS-kernel/osdTime.cpp |
2193 | index 1350c1c..1350c1c 100644 |
2194 | --- a/src/osi/os/RTEMS/osdTime.cpp |
2195 | +++ b/src/osi/os/RTEMS-kernel/osdTime.cpp |
2196 | diff --git a/src/osi/os/RTEMS/osdTime.h b/src/osi/os/RTEMS-kernel/osdTime.h |
2197 | index 55e3bc2..55e3bc2 100644 |
2198 | --- a/src/osi/os/RTEMS/osdTime.h |
2199 | +++ b/src/osi/os/RTEMS-kernel/osdTime.h |
2200 | diff --git a/src/osi/os/RTEMS/osiUnistd.h b/src/osi/os/RTEMS-kernel/osiUnistd.h |
2201 | index c0a6e22..c0a6e22 100644 |
2202 | --- a/src/osi/os/RTEMS/osiUnistd.h |
2203 | +++ b/src/osi/os/RTEMS-kernel/osiUnistd.h |
2204 | diff --git a/src/osi/os/RTEMS-posix/osdInterrupt.c b/src/osi/os/RTEMS-posix/osdInterrupt.c |
2205 | new file mode 100644 |
2206 | index 0000000..4d4ead6 |
2207 | --- /dev/null |
2208 | +++ b/src/osi/os/RTEMS-posix/osdInterrupt.c |
2209 | @@ -0,0 +1,59 @@ |
2210 | +/*************************************************************************\ |
2211 | +* Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne |
2212 | +* National Laboratory. |
2213 | +* Copyright (c) 2002 The Regents of the University of California, as |
2214 | +* Operator of Los Alamos National Laboratory. |
2215 | +* EPICS BASE is distributed subject to a Software License Agreement found |
2216 | +* in file LICENSE that is included with this distribution. |
2217 | +\*************************************************************************/ |
2218 | +/* osi/default/osdInterrupt.c */ |
2219 | + |
2220 | +/* Author: Marty Kraimer Date: 15JUL99 */ |
2221 | + |
2222 | +#include <stddef.h> |
2223 | +#include <string.h> |
2224 | +#include <stdlib.h> |
2225 | +#include <stddef.h> |
2226 | +#include <stdio.h> |
2227 | + |
2228 | +#define epicsExportSharedSymbols |
2229 | +#include "epicsMutex.h" |
2230 | +#include "epicsThread.h" |
2231 | +#include "cantProceed.h" |
2232 | +#include "errlog.h" |
2233 | +#include "epicsInterrupt.h" |
2234 | + |
2235 | +#include <rtems/bspIo.h> |
2236 | +#include <rtems.h> |
2237 | + |
2238 | +epicsShareFunc int epicsInterruptLock() |
2239 | +{ |
2240 | + rtems_interrupt_level level; |
2241 | + |
2242 | + rtems_interrupt_disable (level); |
2243 | + return level; |
2244 | +} |
2245 | + |
2246 | +epicsShareFunc void epicsInterruptUnlock(int key) |
2247 | +{ |
2248 | + rtems_interrupt_level level = key; |
2249 | + |
2250 | + rtems_interrupt_enable (level); |
2251 | +} |
2252 | + |
2253 | +epicsShareFunc int epicsInterruptIsInterruptContext() |
2254 | +{ |
2255 | + return rtems_interrupt_is_in_progress (); |
2256 | +} |
2257 | + |
2258 | +epicsShareFunc void epicsInterruptContextMessage(const char *message) |
2259 | +{ |
2260 | + printk("%s", message); |
2261 | +} |
2262 | + |
2263 | + |
2264 | + |
2265 | + |
2266 | + |
2267 | + |
2268 | + |
2269 | diff --git a/src/osi/os/RTEMS-posix/osdMessageQueue.cpp b/src/osi/os/RTEMS-posix/osdMessageQueue.cpp |
2270 | new file mode 100644 |
2271 | index 0000000..b763da1 |
2272 | --- /dev/null |
2273 | +++ b/src/osi/os/RTEMS-posix/osdMessageQueue.cpp |
2274 | @@ -0,0 +1,163 @@ |
2275 | +/*************************************************************************\ |
2276 | +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne |
2277 | +* National Laboratory. |
2278 | +* Copyright (c) 2002 The Regents of the University of California, as |
2279 | +* Operator of Los Alamos National Laboratory. |
2280 | +* Copyright (c) 2017 Fritz-Haber-Institut der Max-Planck-Gesellschaft |
2281 | +* EPICS BASE is distributed subject to a Software License Agreement found |
2282 | +* in file LICENSE that is included with this distribution. |
2283 | +\*************************************************************************/ |
2284 | +/* |
2285 | + * Author W. Eric Norum |
2286 | + * Heinz Junkes |
2287 | + * |
2288 | + * Adapted to rtems4.12 |
2289 | + * -> posix message queues |
2290 | + * remove all internal calls (_xxx), remove e.g. Objects_Locations etc. |
2291 | + */ |
2292 | + |
2293 | +/* |
2294 | + * We want to access information which is |
2295 | + * normally hidden from application programs. |
2296 | + */ |
2297 | +#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__ 1 |
2298 | + |
2299 | +#define epicsExportSharedSymbols |
2300 | +#include <assert.h> |
2301 | +#include <stdio.h> |
2302 | +#include <stdlib.h> |
2303 | +#include <string.h> |
2304 | +#include <rtems.h> |
2305 | +#include <rtems/error.h> |
2306 | +#include "epicsMessageQueue.h" |
2307 | +#include "errlog.h" |
2308 | +#include <epicsAtomic.h> |
2309 | + |
2310 | +#include <errno.h> |
2311 | +#include <mqueue.h> |
2312 | +#include <fcntl.h> |
2313 | + |
2314 | +epicsShareFunc epicsMessageQueueId epicsShareAPI |
2315 | +epicsMessageQueueCreate(unsigned int capacity, unsigned int maximumMessageSize) |
2316 | +{ |
2317 | + struct mq_attr the_attr; |
2318 | + epicsMessageQueueId id = (epicsMessageQueueId)calloc(1, sizeof(*id)); |
2319 | + |
2320 | + epicsAtomicIncrIntT(&id->idCnt); |
2321 | + sprintf(id->name, "MQ_%010d",epicsAtomicGetIntT(&id->idCnt)); |
2322 | + the_attr.mq_maxmsg = capacity; |
2323 | + the_attr.mq_msgsize = maximumMessageSize; |
2324 | + id->id = mq_open(id->name, O_RDWR | O_CREAT | O_EXCL, 0644, &the_attr); |
2325 | + if (id->id < 0) { |
2326 | + errlogPrintf ("Can't create message queue: %s\n", strerror (errno)); |
2327 | + return NULL; |
2328 | + } |
2329 | + return id; |
2330 | +} |
2331 | + |
2332 | +epicsShareFunc void epicsShareAPI epicsMessageQueueDestroy( |
2333 | + epicsMessageQueueId id) |
2334 | +{ |
2335 | + int rv; |
2336 | + rv = mq_close(id->id); |
2337 | + if( rv ) { |
2338 | + errlogPrintf("epicsMessageQueueDestroy mq_close failed: %s\n", |
2339 | + strerror(rv)); |
2340 | + } |
2341 | + rv = mq_unlink(id->name); |
2342 | + if( rv ) { |
2343 | + errlogPrintf("epicsMessageQueueDestroy mq_unlink %s failed: %s\n", |
2344 | + id->name, strerror(rv)); |
2345 | + } |
2346 | + free(id); |
2347 | +} |
2348 | + |
2349 | +epicsShareFunc int epicsShareAPI epicsMessageQueueTrySend( |
2350 | + epicsMessageQueueId id, |
2351 | + void *message, |
2352 | + unsigned int messageSize) |
2353 | +{ |
2354 | + struct timespec ts; |
2355 | + clock_gettime(CLOCK_REALTIME, &ts); |
2356 | + return mq_timedsend(id->id, (char const *)message, messageSize, 0, &ts); |
2357 | +} |
2358 | + |
2359 | +epicsShareFunc int epicsShareAPI epicsMessageQueueSendWithTimeout( |
2360 | + epicsMessageQueueId id, |
2361 | + void *message, |
2362 | + unsigned int messageSize, |
2363 | + double timeout) |
2364 | +{ |
2365 | + struct timespec ts; |
2366 | + unsigned long micros; |
2367 | + |
2368 | + // assume timeout in sec |
2369 | + micros = (unsigned long)(timeout * 1000000.0); |
2370 | + clock_gettime(CLOCK_REALTIME, &ts); |
2371 | + ts.tv_sec += micros / 1000000L; |
2372 | + ts.tv_nsec += (micros % 1000000L) * 1000L; |
2373 | + |
2374 | + return mq_timedsend (id->id, (const char *)message, messageSize, 0, &ts); |
2375 | +} |
2376 | + |
2377 | +epicsShareFunc int epicsShareAPI epicsMessageQueueTryReceive( |
2378 | + epicsMessageQueueId id, |
2379 | + void *message, |
2380 | + unsigned int size) |
2381 | +{ |
2382 | + struct timespec ts; |
2383 | + clock_gettime(CLOCK_REALTIME, &ts); |
2384 | + return mq_timedreceive(id->id, (char *)message, size, NULL, &ts); |
2385 | +} |
2386 | + |
2387 | +epicsShareFunc int epicsShareAPI epicsMessageQueueReceiveWithTimeout( |
2388 | + epicsMessageQueueId id, |
2389 | + void *message, |
2390 | + unsigned int size, |
2391 | + double timeout) |
2392 | +{ |
2393 | + unsigned long micros; |
2394 | + struct timespec ts; |
2395 | + |
2396 | + micros = (unsigned long)(timeout * 1000000.0); |
2397 | + clock_gettime(CLOCK_REALTIME, &ts); |
2398 | + ts.tv_sec += micros / 1000000L; |
2399 | + ts.tv_nsec += (micros % 1000000L) * 1000L; |
2400 | + |
2401 | + return mq_timedreceive(id->id, (char *)message, size, NULL, &ts); |
2402 | +} |
2403 | + |
2404 | +epicsShareFunc int epicsShareAPI epicsMessageQueuePending( |
2405 | + epicsMessageQueueId id) |
2406 | +{ |
2407 | + int rv; |
2408 | + struct mq_attr the_attr; |
2409 | + |
2410 | + rv = mq_getattr(id->id, &the_attr); |
2411 | + if (rv) { |
2412 | + errlogPrintf("Epics Message queue %x (%s) get attr failed: %s\n", |
2413 | + (unsigned int)id->id, id->name, strerror(rv)); |
2414 | + return -1; |
2415 | + } |
2416 | + return the_attr.mq_curmsgs; |
2417 | +} |
2418 | + |
2419 | +epicsShareFunc void epicsShareAPI epicsMessageQueueShow( |
2420 | + epicsMessageQueueId id, |
2421 | + int level) |
2422 | +{ |
2423 | + int rv; |
2424 | + struct mq_attr the_attr; |
2425 | + |
2426 | + rv = mq_getattr(id->id, &the_attr); |
2427 | + if (rv) { |
2428 | + errlogPrintf("Epics Message queue %x (%s) get attr failed: %s\n", |
2429 | + (unsigned int)id->id, id->id, strerror(rv)); |
2430 | + } |
2431 | + |
2432 | + printf("Message Queue Used:%ld Max Msg:%lu", the_attr.mq_curmsgs, the_attr.mq_maxmsg); |
2433 | + if (level >= 1) |
2434 | + printf(" Maximum size:%lu", the_attr.mq_msgsize); |
2435 | + |
2436 | + printf("\n"); |
2437 | +} |
2438 | diff --git a/src/osi/os/RTEMS-posix/osdMessageQueue.h b/src/osi/os/RTEMS-posix/osdMessageQueue.h |
2439 | new file mode 100644 |
2440 | index 0000000..fccb2d2 |
2441 | --- /dev/null |
2442 | +++ b/src/osi/os/RTEMS-posix/osdMessageQueue.h |
2443 | @@ -0,0 +1,31 @@ |
2444 | +/*************************************************************************\ |
2445 | + * * Copyright (c) 2002 The University of Chicago, as Operator of Argonne |
2446 | + * * National Laboratory. |
2447 | + * * Copyright (c) 2002 The Regents of the University of California, as |
2448 | + * * Operator of Los Alamos National Laboratory. |
2449 | + * * Copyright (c) 2017 Fritz-Haber-Institut der Max-Planck-Gesellschaft |
2450 | + * * EPICS BASE is distributed subject to a Software License Agreement found |
2451 | + * * in file LICENSE that is included with this distribution. |
2452 | + * \*************************************************************************/ |
2453 | +/* |
2454 | + * Author W. Eric Norum |
2455 | + * Heinz Junkes |
2456 | + * |
2457 | + * Eric's note : Very thin shims around vxWorks routines |
2458 | + * |
2459 | + * Adapted to rtems4.12 |
2460 | + * -> posix message queues |
2461 | + */ |
2462 | + |
2463 | +#include <rtems.h> |
2464 | +#include <mqueue.h> |
2465 | + |
2466 | +struct epicsMessageQueueOSD { |
2467 | + mqd_t id; |
2468 | + char name[24]; |
2469 | + int idCnt; |
2470 | + |
2471 | +}; |
2472 | + |
2473 | +#define epicsMessageQueueSend(q,m,l) (mq_send((q)->id, (const char*)(m), (l), 0)) |
2474 | +#define epicsMessageQueueReceive(q,m,s) (mq_receive((q)->id, (char*)(m), (s), NULL)) |
2475 | diff --git a/src/osi/os/RTEMS-posix/osdMutex.c b/src/osi/os/RTEMS-posix/osdMutex.c |
2476 | new file mode 100644 |
2477 | index 0000000..7f4aa62 |
2478 | --- /dev/null |
2479 | +++ b/src/osi/os/RTEMS-posix/osdMutex.c |
2480 | @@ -0,0 +1,6 @@ |
2481 | +#include <rtems.h> |
2482 | +#include <rtems/error.h> |
2483 | +#include <rtems/rtems/tasks.h> |
2484 | +#include <rtems/score/threadimpl.h> |
2485 | + |
2486 | +#include "../posix/osdMutex.c" |
2487 | diff --git a/src/osi/os/RTEMS-posix/osdPoolStatus.c b/src/osi/os/RTEMS-posix/osdPoolStatus.c |
2488 | new file mode 100644 |
2489 | index 0000000..cdd8941 |
2490 | --- /dev/null |
2491 | +++ b/src/osi/os/RTEMS-posix/osdPoolStatus.c |
2492 | @@ -0,0 +1,34 @@ |
2493 | +/*************************************************************************\ |
2494 | +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne |
2495 | +* National Laboratory. |
2496 | +* Copyright (c) 2002 The Regents of the University of California, as |
2497 | +* Operator of Los Alamos National Laboratory. |
2498 | +* Copyright (c) 2017 Fritz-Haber-Institut der Max-Planck-Gesellschaft |
2499 | +* EPICS BASE is distributed subject to a Software License Agreement found |
2500 | +* in file LICENSE that is included with this distribution. |
2501 | +\*************************************************************************/ |
2502 | + |
2503 | +/* |
2504 | + * Heinz Junkes |
2505 | + * Adapted to rtems4.12 |
2506 | + */ |
2507 | + |
2508 | +#include <rtems.h> |
2509 | +#include <rtems/malloc.h> |
2510 | +#include <rtems/score/heap.h> |
2511 | +#define epicsExportSharedSymbols |
2512 | +#include "osiPoolStatus.h" |
2513 | + |
2514 | +/* |
2515 | + * osiSufficentSpaceInPool () |
2516 | + * |
2517 | + */ |
2518 | +epicsShareFunc int epicsShareAPI osiSufficentSpaceInPool ( size_t contiguousBlockSize ) |
2519 | +{ |
2520 | + unsigned long n; |
2521 | + Heap_Information_block info; |
2522 | + |
2523 | + malloc_info( &info ); |
2524 | + n = info.Stats.size - (unsigned long)(info.Stats.lifetime_allocated - info.Stats.lifetime_freed); |
2525 | + return (n > (50000 + contiguousBlockSize)); |
2526 | +} |
2527 | diff --git a/src/osi/os/RTEMS-posix/osdSock.h b/src/osi/os/RTEMS-posix/osdSock.h |
2528 | new file mode 100644 |
2529 | index 0000000..103cdd7 |
2530 | --- /dev/null |
2531 | +++ b/src/osi/os/RTEMS-posix/osdSock.h |
2532 | @@ -0,0 +1,112 @@ |
2533 | +/*************************************************************************\ |
2534 | +* Copyright (c) 2002 The University of Saskatchewan |
2535 | +* Copyright (c) 2017 Fritz-Haber-Institut der Max-Planck-Gesellschaft |
2536 | +* EPICS BASE is distributed subject to a Software License Agreement found |
2537 | +* in file LICENSE that is included with this distribution. |
2538 | +\*************************************************************************/ |
2539 | +/* |
2540 | + * RTEMS osdSock.h |
2541 | + * Author: W. Eric Norum |
2542 | + * Heinz Junkes |
2543 | + * |
2544 | + * Adapted to rtems4.12 |
2545 | + */ |
2546 | +#ifndef osdSockH |
2547 | +#define osdSockH |
2548 | + |
2549 | +#include <errno.h> |
2550 | + |
2551 | +#include <sys/types.h> |
2552 | +#include <sys/param.h> |
2553 | +#include <sys/time.h> |
2554 | +#include <sys/socket.h> |
2555 | +#include <sys/ioctl.h> |
2556 | +#include <netinet/in.h> |
2557 | +#include <netinet/tcp.h> |
2558 | +#include <arpa/inet.h> |
2559 | +#include <net/if.h> |
2560 | +#include <netdb.h> |
2561 | +#include <ifaddrs.h> /* getifaddrs() */ |
2562 | +#include <unistd.h> |
2563 | + |
2564 | +#ifdef __cplusplus |
2565 | +extern "C" { |
2566 | +#endif |
2567 | + |
2568 | +int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); |
2569 | + |
2570 | +#ifdef __cplusplus |
2571 | +} |
2572 | +#endif |
2573 | + |
2574 | + |
2575 | +#ifndef IPPORT_USERRESERVED |
2576 | +#define IPPORT_USERRESERVED 5000 |
2577 | +#endif |
2578 | + |
2579 | +#define USE_IFADDRS |
2580 | + |
2581 | +typedef int SOCKET; |
2582 | +#define INVALID_SOCKET (-1) |
2583 | +#define SOCKERRNO errno |
2584 | +#define socket_ioctl(A,B,C) ioctl(A,B,C) |
2585 | +typedef int osiSockIoctl_t; |
2586 | +typedef socklen_t osiSocklen_t; |
2587 | + |
2588 | +typedef char osiSockOptMcastLoop_t; |
2589 | + |
2590 | +#define FD_IN_FDSET(FD) ((FD)<FD_SETSIZE) |
2591 | + |
2592 | +#define SOCK_EWOULDBLOCK EWOULDBLOCK |
2593 | +#define SOCK_ENOBUFS ENOBUFS |
2594 | +#define SOCK_ECONNRESET ECONNRESET |
2595 | +#define SOCK_ETIMEDOUT ETIMEDOUT |
2596 | +#define SOCK_EACCES EACCES |
2597 | +#define SOCK_EADDRINUSE EADDRINUSE |
2598 | +#define SOCK_EADDRNOTAVAIL EADDRNOTAVAIL |
2599 | +#define SOCK_ECONNREFUSED ECONNREFUSED |
2600 | +#define SOCK_ECONNABORTED ECONNABORTED |
2601 | +#define SOCK_EINPROGRESS EINPROGRESS |
2602 | +#define SOCK_EISCONN EISCONN |
2603 | +#define SOCK_EALREADY EALREADY |
2604 | +#define SOCK_EINVAL EINVAL |
2605 | +#define SOCK_EINTR EINTR |
2606 | +#define SOCK_EPIPE EPIPE |
2607 | +#define SOCK_EMFILE EMFILE |
2608 | +#define SOCK_SHUTDOWN EPIPE |
2609 | +#define SOCK_ENOTSOCK ENOTSOCK |
2610 | +#define SOCK_EBADF EBADF |
2611 | + |
2612 | +#include <sys/time.h> |
2613 | +#include <sys/types.h> |
2614 | +#include <unistd.h> |
2615 | + |
2616 | +#ifndef INADDR_LOOPBACK |
2617 | +#define INADDR_LOOPBACK (u_long)0x7F000001 |
2618 | +#endif |
2619 | + |
2620 | +#ifndef INADDR_NONE |
2621 | +# define INADDR_NONE (0xffffffff) |
2622 | +#endif |
2623 | + |
2624 | +/* |
2625 | + * For shutdown() |
2626 | + */ |
2627 | +#ifndef SHUT_RD |
2628 | +# define SHUT_RD 0 |
2629 | +#endif |
2630 | + |
2631 | +#ifndef SHUT_WR |
2632 | +# define SHUT_WR 1 |
2633 | +#endif |
2634 | + |
2635 | +#ifndef SHUT_RDWR |
2636 | +# define SHUT_RDWR 2 |
2637 | +#endif |
2638 | + |
2639 | +/* |
2640 | + * Ensure that we get the right network code in default/osdNetIntf.c. |
2641 | + */ |
2642 | +#define ifreq_size(pifreq) (pifreq->ifr_addr.sa_len + sizeof(pifreq->ifr_name)) |
2643 | + |
2644 | +#endif /*osdSockH*/ |
2645 | diff --git a/src/osi/os/RTEMS-posix/osdThread.c b/src/osi/os/RTEMS-posix/osdThread.c |
2646 | new file mode 100644 |
2647 | index 0000000..2b51fdb |
2648 | --- /dev/null |
2649 | +++ b/src/osi/os/RTEMS-posix/osdThread.c |
2650 | @@ -0,0 +1,1042 @@ |
2651 | +/*************************************************************************\ |
2652 | +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne |
2653 | +* National Laboratory. |
2654 | +* Copyright (c) 2002 The Regents of the University of California, as |
2655 | +* Operator of Los Alamos National Laboratory. |
2656 | +* Copyright (c) 2013 ITER Organization. |
2657 | +* Copyright (c) 2017 Fritz-Haber-Institut der Max-Planck-Gesellschaft |
2658 | +* EPICS BASE is distributed subject to a Software License Agreement found |
2659 | +* in file LICENSE that is included with this distribution. |
2660 | +\*************************************************************************/ |
2661 | + |
2662 | +/* Author: Marty Kraimer Date: 18JAN2000 |
2663 | + Heinz Junkes Date: 06APR2017 |
2664 | +*/ |
2665 | + |
2666 | +/* This is a posix implementation of epicsThread */ |
2667 | +#include <stddef.h> |
2668 | +#include <stdlib.h> |
2669 | +#include <stddef.h> |
2670 | +#include <string.h> |
2671 | +#include <stdio.h> |
2672 | +#include <errno.h> |
2673 | +#include <time.h> |
2674 | +#include <pthread.h> |
2675 | +#include <signal.h> |
2676 | +#include <sched.h> |
2677 | +#include <unistd.h> |
2678 | + |
2679 | +#define XSTR(x) STR(x) |
2680 | +#define STR(x) #x |
2681 | + |
2682 | +#if defined(__rtems__) |
2683 | +/* RTEMS defines _POSIX_MEMLOCK as 1 in features.h which is wrong */ |
2684 | +#undef _POSIX_MEMLOCK |
2685 | +#endif |
2686 | + |
2687 | +#if defined(_POSIX_MEMLOCK) && _POSIX_MEMLOCK > 0 |
2688 | +#include <sys/mman.h> |
2689 | +#endif |
2690 | + |
2691 | +#define epicsExportSharedSymbols |
2692 | +#include "epicsStdio.h" |
2693 | +#include "ellLib.h" |
2694 | +#include "epicsEvent.h" |
2695 | +#include "epicsMutex.h" |
2696 | +#include "epicsString.h" |
2697 | +#include "epicsThread.h" |
2698 | +#include "cantProceed.h" |
2699 | +#include "errlog.h" |
2700 | +#include "epicsAssert.h" |
2701 | +#include "epicsExit.h" |
2702 | + |
2703 | +epicsShareFunc void epicsThreadShowInfo(epicsThreadOSD *pthreadInfo, unsigned int level); |
2704 | +epicsShareFunc void osdThreadHooksRun(epicsThreadId id); |
2705 | +epicsShareFunc void osdThreadHooksRunMain(epicsThreadId id); |
2706 | + |
2707 | +static int mutexLock(pthread_mutex_t *id) |
2708 | +{ |
2709 | + int status; |
2710 | + |
2711 | + while(1) { |
2712 | + status = pthread_mutex_lock(id); |
2713 | + if(status!=EINTR) return status; |
2714 | + fprintf(stderr,"pthread_mutex_lock returned EINTR. Violates SUSv3\n"); |
2715 | + } |
2716 | +} |
2717 | + |
2718 | +#if defined DONT_USE_POSIX_THREAD_PRIORITY_SCHEDULING |
2719 | +#undef _POSIX_THREAD_PRIORITY_SCHEDULING |
2720 | +#endif |
2721 | + |
2722 | +typedef struct commonAttr{ |
2723 | + pthread_attr_t attr; |
2724 | + struct sched_param schedParam; |
2725 | + int maxPriority; |
2726 | + int minPriority; |
2727 | + int schedPolicy; |
2728 | + int usePolicy; |
2729 | +} commonAttr; |
2730 | + |
2731 | +#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 |
2732 | +typedef struct { |
2733 | + int min_pri, max_pri; |
2734 | + int policy; |
2735 | + int ok; |
2736 | +} priAvailable; |
2737 | +#endif |
2738 | + |
2739 | +static pthread_key_t getpthreadInfo; |
2740 | +static pthread_mutex_t onceLock; |
2741 | +static pthread_mutex_t listLock; |
2742 | +static ELLLIST pthreadList = ELLLIST_INIT; |
2743 | +static commonAttr *pcommonAttr = 0; |
2744 | +static int epicsThreadOnceCalled = 0; |
2745 | + |
2746 | |
2747 | +static epicsThreadOSD *createImplicit(void); |
2748 | + |
2749 | +#define checkStatus(status, message) \ |
2750 | + if ((status)) {\ |
2751 | + errlogPrintf("%s error %s\n", (message), strerror((status))); \ |
2752 | + } |
2753 | + |
2754 | +#define checkStatusQuit(status, message, method) \ |
2755 | + if ((status)) { \ |
2756 | + errlogPrintf("%s error %s\n", (message), strerror((status))); \ |
2757 | + cantProceed((method)); \ |
2758 | + } |
2759 | + |
2760 | +/* The following are for use in once, which is only invoked from epicsThreadInit |
2761 | + * Until epicsThreadInit completes errlogInit will not work. |
2762 | + * They must also be used in init_threadInfo otherwise errlogInit could get |
2763 | + * called recursively. |
2764 | + */ |
2765 | +#define checkStatusOnce(status, message) \ |
2766 | + if ((status)) {\ |
2767 | + fprintf(stderr, "%s error %s\n", (message), strerror((status))); \ |
2768 | + } |
2769 | + |
2770 | +#define checkStatusOnceQuit(status, message, method) \ |
2771 | + if ((status)) { \ |
2772 | + fprintf(stderr, "%s error %s", (message), strerror((status))); \ |
2773 | + fprintf(stderr, "in %s\n", (method)); \ |
2774 | + fprintf(stderr, "epicsThreadInit can't proceed. Program exiting\n"); \ |
2775 | + exit(-1); \ |
2776 | + } |
2777 | + |
2778 | +epicsShareFunc int epicsThreadGetPosixPriority(epicsThreadId pthreadInfo) |
2779 | +{ |
2780 | + assert(epicsThreadOnceCalled); |
2781 | + return(epicsThreadGetPosixPriorityValue(pthreadInfo->osiPriority)); |
2782 | +} |
2783 | + |
2784 | +static void setSchedulingPolicy(epicsThreadOSD *pthreadInfo,int policy) |
2785 | +{ |
2786 | +#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 |
2787 | + int status; |
2788 | + |
2789 | + if (!pcommonAttr->usePolicy) return; |
2790 | + |
2791 | + status = pthread_attr_getschedparam( |
2792 | + &pthreadInfo->attr,&pthreadInfo->schedParam); |
2793 | + checkStatusOnce(status,"pthread_attr_getschedparam"); |
2794 | + |
2795 | + pthreadInfo->schedParam.sched_priority = epicsThreadGetPosixPriority(pthreadInfo); |
2796 | + pthreadInfo->schedPolicy = policy; |
2797 | + status = pthread_attr_setschedpolicy( |
2798 | + &pthreadInfo->attr,policy); |
2799 | + checkStatusOnce(status,"pthread_attr_setschedpolicy"); |
2800 | + |
2801 | + status = pthread_attr_setschedparam( |
2802 | + &pthreadInfo->attr,&pthreadInfo->schedParam); |
2803 | + checkStatusOnce(status,"pthread_attr_setschedparam"); |
2804 | + |
2805 | + status = pthread_attr_setinheritsched( |
2806 | + &pthreadInfo->attr,PTHREAD_EXPLICIT_SCHED); |
2807 | + checkStatusOnce(status,"pthread_attr_setinheritsched"); |
2808 | +#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ |
2809 | +} |
2810 | + |
2811 | |
2812 | +static epicsThreadOSD * create_threadInfo(const char *name) |
2813 | +{ |
2814 | + epicsThreadOSD *pthreadInfo; |
2815 | + |
2816 | + /* sizeof(epicsThreadOSD) includes one byte for the '\0' */ |
2817 | + pthreadInfo = calloc(1,sizeof(*pthreadInfo) + strlen(name)); |
2818 | + if(!pthreadInfo) |
2819 | + return NULL; |
2820 | + |
2821 | + pthreadInfo->suspendEvent = epicsEventCreate(epicsEventEmpty); |
2822 | + if(!pthreadInfo->suspendEvent){ |
2823 | + free(pthreadInfo); |
2824 | + return NULL; |
2825 | + } |
2826 | + |
2827 | + strcpy(pthreadInfo->name, name); |
2828 | + return pthreadInfo; |
2829 | +} |
2830 | + |
2831 | +static epicsThreadOSD * init_threadInfo(const char *name, |
2832 | + unsigned int priority, unsigned int stackSize, |
2833 | + EPICSTHREADFUNC funptr,void *parm) |
2834 | +{ |
2835 | + epicsThreadOSD *pthreadInfo; |
2836 | + int status; |
2837 | + |
2838 | + pthreadInfo = create_threadInfo(name); |
2839 | + if(!pthreadInfo) |
2840 | + return NULL; |
2841 | + |
2842 | + pthreadInfo->createFunc = funptr; |
2843 | + pthreadInfo->createArg = parm; |
2844 | + status = pthread_attr_init(&pthreadInfo->attr); |
2845 | + checkStatusOnce(status,"pthread_attr_init"); |
2846 | + if(status) return 0; |
2847 | + |
2848 | + status = pthread_attr_setdetachstate( |
2849 | + &pthreadInfo->attr, PTHREAD_CREATE_DETACHED); |
2850 | + checkStatusOnce(status,"pthread_attr_setdetachstate"); |
2851 | +#if defined (_POSIX_THREAD_ATTR_STACKSIZE) |
2852 | +#if ! defined (OSITHREAD_USE_DEFAULT_STACK) |
2853 | + status = pthread_attr_setstacksize( &pthreadInfo->attr,(size_t)stackSize); |
2854 | + checkStatusOnce(status,"pthread_attr_setstacksize"); |
2855 | +#endif /*OSITHREAD_USE_DEFAULT_STACK*/ |
2856 | +#endif /*_POSIX_THREAD_ATTR_STACKSIZE*/ |
2857 | + status = pthread_attr_setscope(&pthreadInfo->attr,PTHREAD_SCOPE_PROCESS); |
2858 | + if(errVerbose) checkStatusOnce(status,"pthread_attr_setscope"); |
2859 | + pthreadInfo->osiPriority = priority; |
2860 | +#if defined (__rtems__) |
2861 | + /* |
2862 | + on rtems startup (posix mode) once get called first |
2863 | + by POSIX_Global_construction |
2864 | + -> Thread_Global)construction |
2865 | + -> ppc_interrupt_disable |
2866 | + -> init(asm) |
2867 | + -> __do_global_ctors)aux(asm) |
2868 | + -> GLOBAL__sub_I_iocshPpdbbase |
2869 | + -> __static_initialization_adn_destruction_0 |
2870 | + -> IochRegister |
2871 | + -> localRegister |
2872 | + -> iocshRegister |
2873 | + -> iocshTableLock |
2874 | + -> epicsThreadOnce |
2875 | + -> epicsThreadInit |
2876 | + -> Once |
2877 | + -> once() |
2878 | + * |
2879 | + * Then all keys etc. get cleaned and Posix_Init gets called. |
2880 | + epicsThreadGetIdSelf failed ... createImplicit gets called and |
2881 | + a new pthreadInfo is created for _main_ |
2882 | + |
2883 | + if (strcmp(name, "_main_")) { |
2884 | + fprintf(stderr," set _main_ paramtere\n"); |
2885 | + pthreadInfo->isRealTimeScheduled = 1; |
2886 | + pthreadInfo->isEpicsThread = 1; |
2887 | + pthreadInfo->tid = pthread_self(); |
2888 | + fprintf(stderr, "tid = 0x%x\n", pthreadInfo->tid); |
2889 | + pthreadInfo->osiPriority = posixThreadGetOsiPriorityValue(pthreadInfo->tid); |
2890 | + } |
2891 | + */ |
2892 | +#endif |
2893 | + |
2894 | + return(pthreadInfo); |
2895 | +} |
2896 | + |
2897 | +static void free_threadInfo(epicsThreadOSD *pthreadInfo) |
2898 | +{ |
2899 | + int status; |
2900 | + |
2901 | + if(pthreadInfo->isOnThreadList) { |
2902 | + status = mutexLock(&listLock); |
2903 | + checkStatusQuit(status,"pthread_mutex_lock","free_threadInfo"); |
2904 | + ellDelete(&pthreadList,&pthreadInfo->node); |
2905 | + status = pthread_mutex_unlock(&listLock); |
2906 | + checkStatusQuit(status,"pthread_mutex_unlock","free_threadInfo"); |
2907 | + } |
2908 | + epicsEventDestroy(pthreadInfo->suspendEvent); |
2909 | + status = pthread_attr_destroy(&pthreadInfo->attr); |
2910 | + checkStatusQuit(status,"pthread_attr_destroy","free_threadInfo"); |
2911 | + free(pthreadInfo); |
2912 | +} |
2913 | + |
2914 | |
2915 | +#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 |
2916 | +/* |
2917 | + * The actually available range priority range (at least under linux) |
2918 | + * may be restricted by resource limitations (but that is ignored |
2919 | + * by sched_get_priority_max()). See bug #835138 which is fixed by |
2920 | + * this code. |
2921 | + */ |
2922 | +static int try_pri(int pri, int policy) |
2923 | +{ |
2924 | +struct sched_param schedp; |
2925 | + schedp.sched_priority = pri; |
2926 | + return pthread_setschedparam(pthread_self(), policy, &schedp); |
2927 | +} |
2928 | + |
2929 | +static void* |
2930 | +find_pri_range(void *arg) |
2931 | +{ |
2932 | +priAvailable *prm = arg; |
2933 | +int min = sched_get_priority_min(prm->policy); |
2934 | +int max = sched_get_priority_max(prm->policy); |
2935 | +int low, try; |
2936 | + |
2937 | + if ( -1 == min || -1 == max ) { |
2938 | + /* something is very wrong; maintain old behavior |
2939 | + * (warning message if sched_get_priority_xxx() fails |
2940 | + * and use default policy's sched_priority [even if |
2941 | + * that is likely to cause epicsThreadCreate to fail |
2942 | + * because that priority is not suitable for SCHED_FIFO]). |
2943 | + */ |
2944 | + prm->min_pri = prm->max_pri = -1; |
2945 | + return 0; |
2946 | + } |
2947 | + |
2948 | + |
2949 | + if ( try_pri(min, prm->policy) ) { |
2950 | + /* cannot create thread at minimum priority; |
2951 | + * probably no permission to use SCHED_FIFO |
2952 | + * at all. However, we still must return |
2953 | + * a priority range accepted by the SCHED_FIFO |
2954 | + * policy. Otherwise, epicsThreadCreate() cannot |
2955 | + * detect the unsufficient permission (EPERM) |
2956 | + * and fall back to a non-RT thread (because |
2957 | + * pthread_attr_setschedparam would fail with |
2958 | + * EINVAL due to the bad priority). |
2959 | + */ |
2960 | + prm->min_pri = prm->max_pri = min; |
2961 | + return 0; |
2962 | + } |
2963 | + |
2964 | + |
2965 | + /* Binary search through available priorities. |
2966 | + * The actually available range may be restricted |
2967 | + * by resource limitations (but that is ignored |
2968 | + * by sched_get_priority_max() [linux]). |
2969 | + */ |
2970 | + low = min; |
2971 | + |
2972 | + while ( low < max ) { |
2973 | + try = (max+low)/2; |
2974 | + if ( try_pri(try, prm->policy) ) { |
2975 | + max = try; |
2976 | + } else { |
2977 | + low = try + 1; |
2978 | + } |
2979 | + } |
2980 | + |
2981 | + prm->min_pri = min; |
2982 | + prm->max_pri = try_pri(max, prm->policy) ? max-1 : max; |
2983 | + prm->ok = 1; |
2984 | + |
2985 | + return 0; |
2986 | +} |
2987 | + |
2988 | +static void findPriorityRange(commonAttr *a_p) |
2989 | +{ |
2990 | +priAvailable arg; |
2991 | +pthread_t id; |
2992 | +void *dummy; |
2993 | +int status; |
2994 | + |
2995 | + arg.policy = a_p->schedPolicy; |
2996 | + arg.ok = 0; |
2997 | + |
2998 | + status = pthread_create(&id, 0, find_pri_range, &arg); |
2999 | + checkStatusOnceQuit(status, "pthread_create","findPriorityRange"); |
3000 | + |
3001 | + status = pthread_join(id, &dummy); |
3002 | + checkStatusOnceQuit(status, "pthread_join","findPriorityRange"); |
3003 | + a_p->minPriority = arg.min_pri; |
3004 | + a_p->maxPriority = arg.max_pri; |
3005 | + a_p->usePolicy = arg.ok; |
3006 | +} |
3007 | +#endif |
3008 | + |
3009 | |
3010 | + |
3011 | +static void once(void) |
3012 | +{ |
3013 | + int status; |
3014 | + status = pthread_key_create(&getpthreadInfo,0); |
3015 | + checkStatusOnceQuit(status,"pthread_key_create","once"); |
3016 | + status = pthread_mutex_init(&onceLock,0); |
3017 | + checkStatusOnceQuit(status,"pthread_mutex_init","once"); |
3018 | + status = pthread_mutex_init(&listLock,0); |
3019 | + checkStatusOnceQuit(status,"pthread_mutex_init","once"); |
3020 | + pcommonAttr = calloc(1,sizeof(commonAttr)); |
3021 | + if(!pcommonAttr) checkStatusOnceQuit(errno,"calloc","once"); |
3022 | + status = pthread_attr_init(&pcommonAttr->attr); |
3023 | + checkStatusOnceQuit(status,"pthread_attr_init","once"); |
3024 | + status = pthread_attr_setdetachstate( |
3025 | + &pcommonAttr->attr, PTHREAD_CREATE_DETACHED); |
3026 | + checkStatusOnce(status,"pthread_attr_setdetachstate"); |
3027 | + status = pthread_attr_setscope(&pcommonAttr->attr,PTHREAD_SCOPE_PROCESS); |
3028 | + if(errVerbose) checkStatusOnce(status,"pthread_attr_setscope"); |
3029 | + |
3030 | +#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 |
3031 | + status = pthread_attr_setschedpolicy( |
3032 | + &pcommonAttr->attr,SCHED_FIFO); |
3033 | + checkStatusOnce(status,"pthread_attr_setschedpolicy"); |
3034 | + status = pthread_attr_getschedpolicy( |
3035 | + &pcommonAttr->attr,&pcommonAttr->schedPolicy); |
3036 | + checkStatusOnce(status,"pthread_attr_getschedpolicy"); |
3037 | + status = pthread_attr_getschedparam( |
3038 | + &pcommonAttr->attr,&pcommonAttr->schedParam); |
3039 | + checkStatusOnce(status,"pthread_attr_getschedparam"); |
3040 | + |
3041 | + findPriorityRange(pcommonAttr); |
3042 | + |
3043 | + if(pcommonAttr->maxPriority == -1) { |
3044 | + pcommonAttr->maxPriority = pcommonAttr->schedParam.sched_priority; |
3045 | + fprintf(stderr,"sched_get_priority_max failed set to %d\n", |
3046 | + pcommonAttr->maxPriority); |
3047 | + } |
3048 | + if(pcommonAttr->minPriority == -1) { |
3049 | + pcommonAttr->minPriority = pcommonAttr->schedParam.sched_priority; |
3050 | + fprintf(stderr,"sched_get_priority_min failed set to %d\n", |
3051 | + pcommonAttr->maxPriority); |
3052 | + } |
3053 | + |
3054 | + if (errVerbose) { |
3055 | + fprintf(stderr, "LRT: min priority: %d max priority %d\n", |
3056 | + pcommonAttr->minPriority, pcommonAttr->maxPriority); |
3057 | + } |
3058 | +#else |
3059 | + if(errVerbose) { |
3060 | + fprintf(stderr,"task priorities are not implemented\n"); |
3061 | + } |
3062 | +#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ |
3063 | + |
3064 | +#if !defined(__rtems__) |
3065 | + epicsThreadOSD *pthreadInfo; |
3066 | + pthreadInfo = init_threadInfo("_main_",0, epicsThreadGetStackSize(epicsThreadStackSmall),0,0); |
3067 | + assert(pthreadInfo!=NULL); |
3068 | + status = pthread_setspecific(getpthreadInfo,(void *)pthreadInfo); |
3069 | + checkStatusOnceQuit(status,"pthread_setspecific","once"); |
3070 | + status = mutexLock(&listLock); |
3071 | + checkStatusOnceQuit(status,"pthread_mutex_lock","once"); |
3072 | + ellAdd(&pthreadList,&pthreadInfo->node); |
3073 | + pthreadInfo->isOnThreadList = 1; |
3074 | + status = pthread_mutex_unlock(&listLock); |
3075 | + checkStatusOnceQuit(status,"pthread_mutex_unlock","once"); |
3076 | +#endif |
3077 | + status = atexit(epicsExitCallAtExits); |
3078 | + checkStatusOnce(status,"atexit"); |
3079 | +#if !defined(__rtems__) |
3080 | + osdThreadHooksRunMain(pthreadInfo); |
3081 | +#endif |
3082 | + epicsThreadOnceCalled = 1; |
3083 | +} |
3084 | + |
3085 | +#if defined(__rtems__) |
3086 | +epicsShareFunc |
3087 | +void rtemsMainInit(int prio) |
3088 | +{ |
3089 | + int status; |
3090 | + epicsThreadOSD *pthreadInfo; |
3091 | + |
3092 | + pthreadInfo = init_threadInfo("_main_", prio, |
3093 | + epicsThreadGetStackSize(epicsThreadStackSmall), 0, 0); |
3094 | + assert(pthreadInfo!=NULL); |
3095 | + |
3096 | + pthreadInfo->isRealTimeScheduled = 1; |
3097 | + pthreadInfo->isEpicsThread = 1; |
3098 | + pthreadInfo->tid = pthread_self(); |
3099 | + pthreadInfo->osiPriority = posixThreadGetOsiPriorityValue(pthreadInfo->tid); |
3100 | + |
3101 | + status = pthread_setspecific(getpthreadInfo,(void *)pthreadInfo); |
3102 | + checkStatusOnceQuit(status,"pthread_setspecific","rtemsMainInit"); |
3103 | + |
3104 | + status = mutexLock(&listLock); |
3105 | + checkStatusOnceQuit(status,"pthread_mutex_lock","once"); |
3106 | + |
3107 | + ellAdd(&pthreadList,&pthreadInfo->node); |
3108 | + pthreadInfo->isOnThreadList = 1; |
3109 | + status = pthread_mutex_unlock(&listLock); |
3110 | + checkStatusOnceQuit(status,"pthread_mutex_unlock","rtemsMainInit"); |
3111 | +} |
3112 | +#endif |
3113 | + |
3114 | +static void * start_routine(void *arg) |
3115 | +{ |
3116 | + epicsThreadOSD *pthreadInfo = (epicsThreadOSD *)arg; |
3117 | + int status; |
3118 | + sigset_t blockAllSig; |
3119 | + |
3120 | + sigfillset(&blockAllSig); |
3121 | + pthread_sigmask(SIG_SETMASK,&blockAllSig,NULL); |
3122 | + status = pthread_setspecific(getpthreadInfo,arg); |
3123 | + checkStatusQuit(status,"pthread_setspecific","start_routine"); |
3124 | + status = mutexLock(&listLock); |
3125 | + checkStatusQuit(status,"pthread_mutex_lock","start_routine"); |
3126 | + ellAdd(&pthreadList,&pthreadInfo->node); |
3127 | + pthreadInfo->isOnThreadList = 1; |
3128 | + status = pthread_mutex_unlock(&listLock); |
3129 | + checkStatusQuit(status,"pthread_mutex_unlock","start_routine"); |
3130 | + osdThreadHooksRun(pthreadInfo); |
3131 | + |
3132 | + (*pthreadInfo->createFunc)(pthreadInfo->createArg); |
3133 | + |
3134 | + epicsExitCallAtThreadExits (); |
3135 | + free_threadInfo(pthreadInfo); |
3136 | + return(0); |
3137 | +} |
3138 | + |
3139 | +static void epicsThreadInit(void) |
3140 | +{ |
3141 | + static pthread_once_t once_control = PTHREAD_ONCE_INIT; |
3142 | + int status = pthread_once(&once_control,once); |
3143 | + checkStatusQuit(status,"pthread_once","epicsThreadInit"); |
3144 | +} |
3145 | + |
3146 | +epicsShareFunc |
3147 | +void epicsThreadRealtimeLock(void) |
3148 | +{ |
3149 | +#if defined(_POSIX_MEMLOCK) && _POSIX_MEMLOCK > 0 |
3150 | + if (pcommonAttr->maxPriority > pcommonAttr->minPriority) { |
3151 | + int status = mlockall(MCL_CURRENT | MCL_FUTURE); |
3152 | + |
3153 | + if (status) { |
3154 | + fprintf(stderr, "epicsThreadRealtimeLock " |
3155 | + "Warning: Unable to lock the virtual address space.\n" |
3156 | + "VM page faults may harm real-time performance.\n"); |
3157 | + } |
3158 | + } |
3159 | +#endif |
3160 | +} |
3161 | + |
3162 | +epicsShareFunc unsigned int epicsShareAPI epicsThreadGetStackSize (epicsThreadStackSizeClass stackSizeClass) |
3163 | +{ |
3164 | +#if defined (OSITHREAD_USE_DEFAULT_STACK) |
3165 | + return 0; |
3166 | +#elif defined(_POSIX_THREAD_ATTR_STACKSIZE) && _POSIX_THREAD_ATTR_STACKSIZE > 0 |
3167 | +#if defined (__rtems__) |
3168 | + #define STACK_SIZE(f) (f * 0x1000 * sizeof(void *)) |
3169 | +#else |
3170 | + #define STACK_SIZE(f) (f * 0x10000 * sizeof(void *)) |
3171 | +#endif |
3172 | + static const unsigned stackSizeTable[epicsThreadStackBig+1] = { |
3173 | + STACK_SIZE(1), STACK_SIZE(2), STACK_SIZE(4) |
3174 | + }; |
3175 | + if (stackSizeClass<epicsThreadStackSmall) { |
3176 | + errlogPrintf("epicsThreadGetStackSize illegal argument (too small)"); |
3177 | + return stackSizeTable[epicsThreadStackBig]; |
3178 | + } |
3179 | + |
3180 | + if (stackSizeClass>epicsThreadStackBig) { |
3181 | + errlogPrintf("epicsThreadGetStackSize illegal argument (too large)"); |
3182 | + return stackSizeTable[epicsThreadStackBig]; |
3183 | + } |
3184 | + |
3185 | + return stackSizeTable[stackSizeClass]; |
3186 | +#else |
3187 | + return 0; |
3188 | +#endif /*_POSIX_THREAD_ATTR_STACKSIZE*/ |
3189 | +} |
3190 | + |
3191 | |
3192 | +epicsShareFunc void epicsShareAPI epicsThreadOnce(epicsThreadOnceId *id, void (*func)(void *), void *arg) |
3193 | +{ |
3194 | + static struct epicsThreadOSD threadOnceComplete; |
3195 | + #define EPICS_THREAD_ONCE_DONE &threadOnceComplete |
3196 | + int status; |
3197 | + |
3198 | + epicsThreadInit(); |
3199 | + status = mutexLock(&onceLock); |
3200 | + if(status) { |
3201 | + fprintf(stderr,"epicsThreadOnce: pthread_mutex_lock returned %s.\n", |
3202 | + strerror(status)); |
3203 | + exit(-1); |
3204 | + } |
3205 | + |
3206 | + if (*id != EPICS_THREAD_ONCE_DONE) { |
3207 | + if (*id == EPICS_THREAD_ONCE_INIT) { /* first call */ |
3208 | + *id = epicsThreadGetIdSelf(); /* mark active */ |
3209 | + status = pthread_mutex_unlock(&onceLock); |
3210 | + checkStatusOnceQuit(status,"pthread_mutex_unlock", "epicsThreadOnce"); |
3211 | + func(arg); |
3212 | + status = mutexLock(&onceLock); |
3213 | + checkStatusOnceQuit(status,"pthread_mutex_lock", "epicsThreadOnce"); |
3214 | + *id = EPICS_THREAD_ONCE_DONE; /* mark done */ |
3215 | + } else if (*id == epicsThreadGetIdSelf()) { |
3216 | + status = pthread_mutex_unlock(&onceLock); |
3217 | + checkStatusOnceQuit(status,"pthread_mutex_unlock", "epicsThreadOnce"); |
3218 | + cantProceed("Recursive epicsThreadOnce() initialization\n"); |
3219 | + } else |
3220 | + while (*id != EPICS_THREAD_ONCE_DONE) { |
3221 | + /* Another thread is in the above func(arg) call. */ |
3222 | + status = pthread_mutex_unlock(&onceLock); |
3223 | + checkStatusOnceQuit(status,"pthread_mutex_unlock", "epicsThreadOnce"); |
3224 | + epicsThreadSleep(epicsThreadSleepQuantum()); |
3225 | + status = mutexLock(&onceLock); |
3226 | + checkStatusOnceQuit(status,"pthread_mutex_lock", "epicsThreadOnce"); |
3227 | + } |
3228 | + } |
3229 | + status = pthread_mutex_unlock(&onceLock); |
3230 | + checkStatusOnceQuit(status,"pthread_mutex_unlock","epicsThreadOnce"); |
3231 | +} |
3232 | + |
3233 | +epicsShareFunc epicsThreadId epicsShareAPI epicsThreadCreate(const char *name, |
3234 | + unsigned int priority, unsigned int stackSize, |
3235 | + EPICSTHREADFUNC funptr,void *parm) |
3236 | +{ |
3237 | + epicsThreadOSD *pthreadInfo; |
3238 | + int status; |
3239 | + sigset_t blockAllSig, oldSig; |
3240 | + |
3241 | + epicsThreadInit(); |
3242 | + assert(pcommonAttr); |
3243 | + sigfillset(&blockAllSig); |
3244 | + pthread_sigmask(SIG_SETMASK,&blockAllSig,&oldSig); |
3245 | + pthreadInfo = init_threadInfo(name,priority,stackSize,funptr,parm); |
3246 | + if(pthreadInfo==0) return 0; |
3247 | + pthreadInfo->isEpicsThread = 1; |
3248 | + setSchedulingPolicy(pthreadInfo,SCHED_FIFO); |
3249 | + pthreadInfo->isRealTimeScheduled = 1; |
3250 | + status = pthread_create(&pthreadInfo->tid,&pthreadInfo->attr, |
3251 | + start_routine,pthreadInfo); |
3252 | + if(status==EPERM){ |
3253 | + /* Try again without SCHED_FIFO*/ |
3254 | + free_threadInfo(pthreadInfo); |
3255 | + pthreadInfo = init_threadInfo(name,priority,stackSize,funptr,parm); |
3256 | + if(pthreadInfo==0) return 0; |
3257 | + pthreadInfo->isEpicsThread = 1; |
3258 | + status = pthread_create(&pthreadInfo->tid,&pthreadInfo->attr, |
3259 | + start_routine,pthreadInfo); |
3260 | + } |
3261 | + checkStatusOnce(status,"pthread_create"); |
3262 | + if(status) { |
3263 | + free_threadInfo(pthreadInfo); |
3264 | + return 0; |
3265 | + } |
3266 | + status = pthread_sigmask(SIG_SETMASK,&oldSig,NULL); |
3267 | + checkStatusOnce(status,"pthread_sigmask"); |
3268 | + return(pthreadInfo); |
3269 | +} |
3270 | + |
3271 | +/* |
3272 | + * Create dummy context for threads not created by epicsThreadCreate(). |
3273 | + */ |
3274 | +static epicsThreadOSD *createImplicit(void) |
3275 | +{ |
3276 | + epicsThreadOSD *pthreadInfo; |
3277 | + char name[64]; |
3278 | + pthread_t tid; |
3279 | + int status; |
3280 | + |
3281 | + tid = pthread_self(); |
3282 | + sprintf(name, "non-EPICS_%08ld", (long)tid); |
3283 | + pthreadInfo = create_threadInfo(name); |
3284 | + assert(pthreadInfo); |
3285 | + pthreadInfo->tid = tid; |
3286 | +#if defined(__rtems__) |
3287 | + pthreadInfo->osiPriority = posixThreadGetOsiPriorityValue(tid); |
3288 | +#endif |
3289 | + status = pthread_setspecific(getpthreadInfo,(void *)pthreadInfo); |
3290 | + checkStatus(status,"pthread_setspecific createImplicit"); |
3291 | + if(status){ |
3292 | + free_threadInfo(pthreadInfo); |
3293 | + return NULL; |
3294 | + } |
3295 | + return pthreadInfo; |
3296 | +} |
3297 | + |
3298 | |
3299 | +epicsShareFunc void epicsShareAPI epicsThreadSuspendSelf(void) |
3300 | +{ |
3301 | + epicsThreadOSD *pthreadInfo; |
3302 | + |
3303 | + epicsThreadInit(); |
3304 | + pthreadInfo = (epicsThreadOSD *)pthread_getspecific(getpthreadInfo); |
3305 | + if(pthreadInfo==NULL) |
3306 | + pthreadInfo = createImplicit(); |
3307 | + pthreadInfo->isSuspended = 1; |
3308 | + epicsEventWait(pthreadInfo->suspendEvent); |
3309 | +} |
3310 | + |
3311 | +epicsShareFunc void epicsShareAPI epicsThreadResume(epicsThreadOSD *pthreadInfo) |
3312 | +{ |
3313 | + assert(epicsThreadOnceCalled); |
3314 | + pthreadInfo->isSuspended = 0; |
3315 | + epicsEventSignal(pthreadInfo->suspendEvent); |
3316 | +} |
3317 | + |
3318 | +epicsShareFunc void epicsShareAPI epicsThreadExitMain(void) |
3319 | +{ |
3320 | + epicsThreadOSD *pthreadInfo; |
3321 | + |
3322 | + epicsThreadInit(); |
3323 | + pthreadInfo = (epicsThreadOSD *)pthread_getspecific(getpthreadInfo); |
3324 | + if(pthreadInfo==NULL) |
3325 | + pthreadInfo = createImplicit(); |
3326 | + if(pthreadInfo->createFunc) { |
3327 | + errlogPrintf("called from non-main thread\n"); |
3328 | + cantProceed("epicsThreadExitMain"); |
3329 | + } |
3330 | + else { |
3331 | + free_threadInfo(pthreadInfo); |
3332 | + pthread_exit(0); |
3333 | + } |
3334 | +} |
3335 | + |
3336 | +epicsShareFunc int posixThreadGetOsiPriorityValue(pthread_t tid) |
3337 | +{ |
3338 | + #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 |
3339 | + struct sched_param param; |
3340 | + int policy; |
3341 | + |
3342 | + if (pthread_getschedparam(tid,&policy,¶m) == 0) { |
3343 | + return (param.sched_priority - pcommonAttr->minPriority) * 100.0 / |
3344 | + (pcommonAttr->maxPriority - pcommonAttr->minPriority + 1); |
3345 | + } |
3346 | +#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ |
3347 | + return 0; |
3348 | +} |
3349 | + |
3350 | +epicsShareFunc int epicsThreadGetPosixPriorityValue(int osiPriority) |
3351 | +{ |
3352 | +#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 |
3353 | + double maxPriority, minPriority, slope, posixPrio; |
3354 | + |
3355 | + if (pcommonAttr->maxPriority==pcommonAttr->minPriority) |
3356 | + return pcommonAttr->maxPriority; |
3357 | + |
3358 | + maxPriority = (double)pcommonAttr->maxPriority; |
3359 | + minPriority = (double)pcommonAttr->minPriority; |
3360 | + slope = (maxPriority - minPriority)/100.0; |
3361 | + posixPrio = (double)osiPriority * slope + minPriority; |
3362 | + return (int) posixPrio; |
3363 | +#else |
3364 | + return 0; |
3365 | +#endif |
3366 | +} |
3367 | + |
3368 | +epicsShareFunc unsigned int epicsShareAPI epicsThreadGetPosixMaxPriorityValue() |
3369 | +{ |
3370 | +#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 |
3371 | + return pcommonAttr->maxPriority; |
3372 | +#else |
3373 | + return 0; |
3374 | +#endif |
3375 | +} |
3376 | +epicsShareFunc unsigned int epicsShareAPI epicsThreadGetPosixMinPriorityValue() |
3377 | +{ |
3378 | +#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 |
3379 | + return pcommonAttr->minPriority; |
3380 | +#else |
3381 | + return 0; |
3382 | +#endif |
3383 | +} |
3384 | + |
3385 | +epicsShareFunc unsigned int epicsShareAPI epicsThreadGetPriority(epicsThreadId pthreadInfo) |
3386 | +{ |
3387 | + assert(epicsThreadOnceCalled); |
3388 | + return pthreadInfo->osiPriority; |
3389 | +} |
3390 | + |
3391 | +epicsShareFunc unsigned int epicsShareAPI epicsThreadGetPrioritySelf(void) |
3392 | +{ |
3393 | + epicsThreadInit(); |
3394 | + return epicsThreadGetPriority(epicsThreadGetIdSelf()); |
3395 | +} |
3396 | + |
3397 | +epicsShareFunc void epicsShareAPI epicsThreadSetPriority(epicsThreadId pthreadInfo,unsigned int priority) |
3398 | +{ |
3399 | +#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 |
3400 | + int status; |
3401 | +#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ |
3402 | + |
3403 | + assert(epicsThreadOnceCalled); |
3404 | + assert(pthreadInfo); |
3405 | + |
3406 | +#if !defined (__rtems__) |
3407 | + if (!pthreadInfo->isEpicsThread) { |
3408 | + fprintf(stderr, "epicsThreadSetPriority called for non-EPICS thread\n"); |
3409 | + return; |
3410 | + } |
3411 | +#endif |
3412 | + pthreadInfo->osiPriority = priority; |
3413 | + if (!pthreadInfo->isRealTimeScheduled) return; |
3414 | + |
3415 | +#if defined (_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 |
3416 | + if(!pcommonAttr->usePolicy) return; |
3417 | + pthreadInfo->schedParam.sched_priority = epicsThreadGetPosixPriority(pthreadInfo); |
3418 | + status = pthread_attr_setschedparam( |
3419 | + &pthreadInfo->attr,&pthreadInfo->schedParam); |
3420 | + if(errVerbose) checkStatus(status,"pthread_attr_setschedparam"); |
3421 | + status = pthread_setschedparam( |
3422 | + pthreadInfo->tid, pthreadInfo->schedPolicy, &pthreadInfo->schedParam); |
3423 | + if(errVerbose) checkStatus(status,"pthread_setschedparam"); |
3424 | +#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ |
3425 | +} |
3426 | + |
3427 | +epicsShareFunc epicsThreadBooleanStatus epicsShareAPI epicsThreadHighestPriorityLevelBelow( |
3428 | + unsigned int priority, unsigned *pPriorityJustBelow) |
3429 | +{ |
3430 | + unsigned newPriority = priority - 1; |
3431 | + |
3432 | + epicsThreadInit(); |
3433 | + assert(pcommonAttr); |
3434 | + |
3435 | +#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 |
3436 | + int diff; |
3437 | + diff = pcommonAttr->maxPriority - pcommonAttr->minPriority; |
3438 | + if(diff<0) diff = -diff; |
3439 | + if(diff>1 && diff <100) newPriority -= 100/(diff+1); |
3440 | +#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ |
3441 | + if (newPriority <= 99) { |
3442 | + *pPriorityJustBelow = newPriority; |
3443 | + return epicsThreadBooleanStatusSuccess; |
3444 | + } |
3445 | + return epicsThreadBooleanStatusFail; |
3446 | +} |
3447 | + |
3448 | +epicsShareFunc epicsThreadBooleanStatus epicsShareAPI epicsThreadLowestPriorityLevelAbove( |
3449 | + unsigned int priority, unsigned *pPriorityJustAbove) |
3450 | +{ |
3451 | + unsigned newPriority = priority + 1; |
3452 | + |
3453 | + epicsThreadInit(); |
3454 | + assert(pcommonAttr); |
3455 | + |
3456 | +#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0 |
3457 | + int diff; |
3458 | + diff = pcommonAttr->maxPriority - pcommonAttr->minPriority; |
3459 | + if(diff<0) diff = -diff; |
3460 | + if(diff>1 && diff <100) newPriority += 100/(diff+1); |
3461 | +#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ |
3462 | + |
3463 | + if (newPriority <= 99) { |
3464 | + *pPriorityJustAbove = newPriority; |
3465 | + return epicsThreadBooleanStatusSuccess; |
3466 | + } |
3467 | + return epicsThreadBooleanStatusFail; |
3468 | +} |
3469 | + |
3470 | |
3471 | +epicsShareFunc int epicsShareAPI epicsThreadIsEqual(epicsThreadId p1, epicsThreadId p2) |
3472 | +{ |
3473 | + assert(epicsThreadOnceCalled); |
3474 | + assert(p1); |
3475 | + assert(p2); |
3476 | + return(pthread_equal(p1->tid,p2->tid)); |
3477 | +} |
3478 | + |
3479 | +epicsShareFunc int epicsShareAPI epicsThreadIsSuspended(epicsThreadId pthreadInfo) { |
3480 | + assert(epicsThreadOnceCalled); |
3481 | + assert(pthreadInfo); |
3482 | + return(pthreadInfo->isSuspended ? 1 : 0); |
3483 | +} |
3484 | + |
3485 | +epicsShareFunc void epicsShareAPI epicsThreadSleep(double seconds) |
3486 | +{ |
3487 | + struct timespec delayTime; |
3488 | + struct timespec remainingTime; |
3489 | + double nanoseconds; |
3490 | + |
3491 | + if (seconds > 0) { |
3492 | + delayTime.tv_sec = seconds; |
3493 | + nanoseconds = (seconds - delayTime.tv_sec) *1e9; |
3494 | + delayTime.tv_nsec = nanoseconds; |
3495 | + } |
3496 | + else { |
3497 | + delayTime.tv_sec = 0; |
3498 | + delayTime.tv_nsec = 0; |
3499 | + } |
3500 | + while (nanosleep(&delayTime, &remainingTime) == -1 && |
3501 | + errno == EINTR) |
3502 | + delayTime = remainingTime; |
3503 | +} |
3504 | + |
3505 | +epicsShareFunc epicsThreadId epicsShareAPI epicsThreadGetIdSelf(void) { |
3506 | + epicsThreadOSD *pthreadInfo; |
3507 | + |
3508 | + epicsThreadInit(); |
3509 | + pthreadInfo = (epicsThreadOSD *)pthread_getspecific(getpthreadInfo); |
3510 | + if(pthreadInfo==NULL) |
3511 | + pthreadInfo = createImplicit(); |
3512 | + assert( pthreadInfo ); |
3513 | + return(pthreadInfo); |
3514 | +} |
3515 | + |
3516 | +epicsShareFunc pthread_t epicsThreadGetPosixThreadId ( epicsThreadId threadId ) |
3517 | +{ |
3518 | + return threadId->tid; |
3519 | +} |
3520 | + |
3521 | +epicsShareFunc epicsThreadId epicsShareAPI epicsThreadGetId(const char *name) { |
3522 | + epicsThreadOSD *pthreadInfo; |
3523 | + int status; |
3524 | + |
3525 | + assert(epicsThreadOnceCalled); |
3526 | + status = mutexLock(&listLock); |
3527 | + checkStatus(status,"pthread_mutex_lock epicsThreadGetId"); |
3528 | + if(status) |
3529 | + return NULL; |
3530 | + pthreadInfo=(epicsThreadOSD *)ellFirst(&pthreadList); |
3531 | + while (pthreadInfo) { |
3532 | + if (strcmp(name,pthreadInfo->name) == 0) break; |
3533 | + pthreadInfo = (epicsThreadOSD *)ellNext(&pthreadInfo->node); |
3534 | + } |
3535 | + status = pthread_mutex_unlock(&listLock); |
3536 | + checkStatus(status,"pthread_mutex_unlock epicsThreadGetId"); |
3537 | + |
3538 | + return(pthreadInfo); |
3539 | +} |
3540 | + |
3541 | +epicsShareFunc const char epicsShareAPI *epicsThreadGetNameSelf() |
3542 | +{ |
3543 | + epicsThreadOSD *pthreadInfo; |
3544 | + |
3545 | + epicsThreadInit(); |
3546 | + pthreadInfo=(epicsThreadOSD *)pthread_getspecific(getpthreadInfo); |
3547 | + if(pthreadInfo==NULL) |
3548 | + pthreadInfo = createImplicit(); |
3549 | + return(pthreadInfo->name); |
3550 | +} |
3551 | + |
3552 | +epicsShareFunc void epicsShareAPI epicsThreadGetName(epicsThreadId pthreadInfo, char *name, size_t size) |
3553 | +{ |
3554 | + assert(epicsThreadOnceCalled); |
3555 | + strncpy(name, pthreadInfo->name, size-1); |
3556 | + name[size-1] = '\0'; |
3557 | +} |
3558 | + |
3559 | |
3560 | +epicsShareFunc void epicsThreadMap(EPICS_THREAD_HOOK_ROUTINE func) |
3561 | +{ |
3562 | + epicsThreadOSD *pthreadInfo; |
3563 | + int status; |
3564 | + |
3565 | + epicsThreadInit(); |
3566 | + status = mutexLock(&listLock); |
3567 | + checkStatus(status, "pthread_mutex_lock epicsThreadMap"); |
3568 | + if (status) |
3569 | + return; |
3570 | + pthreadInfo=(epicsThreadOSD *)ellFirst(&pthreadList); |
3571 | + while (pthreadInfo) { |
3572 | + func(pthreadInfo); |
3573 | + pthreadInfo = (epicsThreadOSD *)ellNext(&pthreadInfo->node); |
3574 | + } |
3575 | + status = pthread_mutex_unlock(&listLock); |
3576 | + checkStatus(status, "pthread_mutex_unlock epicsThreadMap"); |
3577 | +} |
3578 | + |
3579 | +epicsShareFunc void epicsShareAPI epicsThreadShowAll(unsigned int level) |
3580 | +{ |
3581 | + epicsThreadOSD *pthreadInfo; |
3582 | + int status; |
3583 | + |
3584 | + epicsThreadInit(); |
3585 | + epicsThreadShow(0,level); |
3586 | + status = mutexLock(&listLock); |
3587 | + checkStatus(status,"pthread_mutex_lock epicsThreadShowAll"); |
3588 | + if(status) |
3589 | + return; |
3590 | + pthreadInfo=(epicsThreadOSD *)ellFirst(&pthreadList); |
3591 | + while(pthreadInfo) { |
3592 | + epicsThreadShowInfo(pthreadInfo,level); |
3593 | + pthreadInfo=(epicsThreadOSD *)ellNext(&pthreadInfo->node); |
3594 | + } |
3595 | + status = pthread_mutex_unlock(&listLock); |
3596 | + checkStatus(status,"pthread_mutex_unlock epicsThreadShowAll"); |
3597 | +} |
3598 | + |
3599 | +epicsShareFunc void epicsShareAPI epicsThreadShow(epicsThreadId showThread, unsigned int level) |
3600 | +{ |
3601 | + epicsThreadOSD *pthreadInfo; |
3602 | + int status; |
3603 | + int found = 0; |
3604 | + |
3605 | + epicsThreadInit(); |
3606 | + if(!showThread) { |
3607 | + epicsThreadShowInfo(0,level); |
3608 | + return; |
3609 | + } |
3610 | + status = mutexLock(&listLock); |
3611 | + checkStatus(status,"pthread_mutex_lock epicsThreadShow"); |
3612 | + if(status) |
3613 | + return; |
3614 | + pthreadInfo=(epicsThreadOSD *)ellFirst(&pthreadList); |
3615 | + while(pthreadInfo) { |
3616 | + if (((epicsThreadId)pthreadInfo == showThread) |
3617 | + || ((epicsThreadId)pthreadInfo->tid == showThread)) { |
3618 | + found = 1; |
3619 | + epicsThreadShowInfo(pthreadInfo,level); |
3620 | + } |
3621 | + pthreadInfo=(epicsThreadOSD *)ellNext(&pthreadInfo->node); |
3622 | + } |
3623 | + status = pthread_mutex_unlock(&listLock); |
3624 | + checkStatus(status,"pthread_mutex_unlock epicsThreadShow"); |
3625 | + if(status) return; |
3626 | + if (!found) |
3627 | + printf("Thread %#lx (%lu) not found.\n", (unsigned long)showThread, (unsigned long)showThread); |
3628 | +} |
3629 | + |
3630 | |
3631 | +epicsShareFunc epicsThreadPrivateId epicsShareAPI epicsThreadPrivateCreate(void) |
3632 | +{ |
3633 | + pthread_key_t *key; |
3634 | + int status; |
3635 | + |
3636 | + epicsThreadInit(); |
3637 | + key = calloc(1,sizeof(pthread_key_t)); |
3638 | + if(!key) |
3639 | + return NULL; |
3640 | + status = pthread_key_create(key,0); |
3641 | + checkStatus(status,"pthread_key_create epicsThreadPrivateCreate"); |
3642 | + if(status) |
3643 | + return NULL; |
3644 | + return((epicsThreadPrivateId)key); |
3645 | +} |
3646 | + |
3647 | +epicsShareFunc void epicsShareAPI epicsThreadPrivateDelete(epicsThreadPrivateId id) |
3648 | +{ |
3649 | + pthread_key_t *key = (pthread_key_t *)id; |
3650 | + int status; |
3651 | + |
3652 | + assert(epicsThreadOnceCalled); |
3653 | + status = pthread_key_delete(*key); |
3654 | + checkStatusQuit(status,"pthread_key_delete","epicsThreadPrivateDelete"); |
3655 | + free((void *)key); |
3656 | +} |
3657 | + |
3658 | +epicsShareFunc void epicsShareAPI epicsThreadPrivateSet (epicsThreadPrivateId id, void *value) |
3659 | +{ |
3660 | + pthread_key_t *key = (pthread_key_t *)id; |
3661 | + int status; |
3662 | + |
3663 | + assert(epicsThreadOnceCalled); |
3664 | + if(errVerbose && !value) |
3665 | + errlogPrintf("epicsThreadPrivateSet: setting value of 0\n"); |
3666 | + status = pthread_setspecific(*key,value); |
3667 | + checkStatusQuit(status,"pthread_setspecific","epicsThreadPrivateSet"); |
3668 | +} |
3669 | + |
3670 | +epicsShareFunc void epicsShareAPI *epicsThreadPrivateGet(epicsThreadPrivateId id) |
3671 | +{ |
3672 | + pthread_key_t *key = (pthread_key_t *)id; |
3673 | + |
3674 | + assert(epicsThreadOnceCalled); |
3675 | + return pthread_getspecific(*key); |
3676 | +} |
3677 | + |
3678 | +epicsShareFunc double epicsShareAPI epicsThreadSleepQuantum () |
3679 | +{ |
3680 | + double hz; |
3681 | + hz = sysconf ( _SC_CLK_TCK ); |
3682 | + if(hz<0) |
3683 | + return 0.0; |
3684 | + return 1.0 / hz; |
3685 | +} |
3686 | + |
3687 | +epicsShareFunc int epicsThreadGetCPUs(void) |
3688 | +{ |
3689 | + long ret; |
3690 | +#ifdef _SC_NPROCESSORS_ONLN |
3691 | + ret = sysconf(_SC_NPROCESSORS_ONLN); |
3692 | + if (ret > 0) |
3693 | + return ret; |
3694 | +#endif |
3695 | +#ifdef _SC_NPROCESSORS_CONF |
3696 | + ret = sysconf(_SC_NPROCESSORS_CONF); |
3697 | + if (ret > 0) |
3698 | + return ret; |
3699 | +#endif |
3700 | + return 1; |
3701 | +} |
3702 | diff --git a/src/osi/os/RTEMS-posix/osdThread.h b/src/osi/os/RTEMS-posix/osdThread.h |
3703 | new file mode 100644 |
3704 | index 0000000..ac27ff0 |
3705 | --- /dev/null |
3706 | +++ b/src/osi/os/RTEMS-posix/osdThread.h |
3707 | @@ -0,0 +1,55 @@ |
3708 | +/*************************************************************************\ |
3709 | +* Copyright (c) 2002 The University of Chicago, as Operator of Argonne |
3710 | +* National Laboratory. |
3711 | +* Copyright (c) 2002 The Regents of the University of California, as |
3712 | +* Operator of Los Alamos National Laboratory. |
3713 | +* EPICS BASE Versions 3.13.7 |
3714 | +* and higher are distributed subject to a Software License Agreement found |
3715 | +* in file LICENSE that is included with this distribution. |
3716 | +\*************************************************************************/ |
3717 | +#ifndef osdThreadh |
3718 | +#define osdThreadh |
3719 | + |
3720 | +#include <pthread.h> |
3721 | + |
3722 | +#include "shareLib.h" |
3723 | +#include "ellLib.h" |
3724 | +#include "epicsEvent.h" |
3725 | + |
3726 | +#ifdef __cplusplus |
3727 | +extern "C" { |
3728 | +#endif |
3729 | + |
3730 | +typedef struct epicsThreadOSD { |
3731 | + ELLNODE node; |
3732 | + pthread_t tid; |
3733 | + pthread_attr_t attr; |
3734 | + struct sched_param schedParam; |
3735 | + int schedPolicy; |
3736 | + EPICSTHREADFUNC createFunc; |
3737 | + void *createArg; |
3738 | + epicsEventId suspendEvent; |
3739 | + int isSuspended; |
3740 | + int isEpicsThread; |
3741 | + int isRealTimeScheduled; |
3742 | + int isOnThreadList; |
3743 | + unsigned int osiPriority; |
3744 | + char name[1]; /* actually larger */ |
3745 | +} epicsThreadOSD; |
3746 | + |
3747 | +epicsShareFunc pthread_t epicsThreadGetPosixThreadId(epicsThreadId id); |
3748 | +epicsShareFunc int epicsThreadGetPosixPriority(epicsThreadId id); |
3749 | +epicsShareFunc int epicsThreadGetPosixPriorityValue(int osiPriority); |
3750 | +epicsShareFunc int posixThreadGetOsiPriorityValue(pthread_t tid); |
3751 | +epicsShareFunc unsigned int epicsShareAPI epicsThreadGetPosixMaxPriorityValue(); |
3752 | +epicsShareFunc unsigned int epicsShareAPI epicsThreadGetPosixMinPriorityValue(); |
3753 | + |
3754 | +#if defined(__rtems__) |
3755 | +epicsShareFunc void rtemsMainInit(int prio); |
3756 | +#endif |
3757 | + |
3758 | +#ifdef __cplusplus |
3759 | +} |
3760 | +#endif |
3761 | + |
3762 | +#endif /* osdThreadh */ |
After a first pass reading through the diff I see two areas which need attention.
1) Parts of my RTEMS testing branch are still included. Not enough to actually work though. I'm referring to the files ne2kpci.*, epicsMakeMemFs.pl, and epicsMemFs.*. I think these could be removed with minimal effort.
2) There is still imo. too much duplication. The files I'd specifically like to see de-duplicated are: rtems_init.c, setBootConfigFr omNVRAM. c, and osdThread.*.