Non-VME RTEMS targets should define pdevLibVME

Bug #1841692 reported by Andrew Johnson
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
EPICS Base
Status tracked in 7.0
7.0
Fix Released
Medium
Andrew Johnson

Bug Description

Support modules that build IOCs with drivers that call devLib routines can't be compiled on non-VME RTEMS targets such as RTEMS-pc386 since the linker fails to find the symbol pdevLibVME. The build *only* fails for RTEMS targets though, other non-VME targets such as Windows or darwin will quite happily compile and link the IOC code. This makes the authors of support modules have to jump through hoops to ensure they don't build IOCs for targets that will fail, or to just let the build fail (many sites don't build for RTEMS anyway).

The RTEMS implementation of devLibVMEOSD.c uses pre-processor conditionals to only define the devLibVME *pdevLibVME pointer inside #if defined(__PPC__) || defined(__mcf528x__)

We could make life much easier for module authors by adding this:

diff --git a/modules/libcom/src/osi/os/RTEMS/devLibVMEOSD.c b/modules/libcom/src/osi/os/RTEMS/devLibVMEOSD.c
index 0a96bad..b8f79e7 100644
--- a/modules/libcom/src/osi/os/RTEMS/devLibVMEOSD.c
+++ b/modules/libcom/src/osi/os/RTEMS/devLibVMEOSD.c
@@ -350,7 +350,12 @@ static void unsolicitedHandlerEPICS(int vectorNumber)
         );
 }

-#endif /* defined(__PPC__) && defined(mpc750) */
+#else /* !defined(__PPC__) && !defined(__mcf528x__) */
+
+/* No known VME interface here, provide a dummy */
+devLibVME *pdevLibVME;
+
+#endif /* defined(__PPC__) || defined(__mcf528x__) */

 /*
  * Some vxWorks convenience routines

With that change (which is identical to the osi/os/default version), the non-VME RTEMS targets will build exactly the same as the workstation OS targets; an IOC that calls devLib will now compile, although it obviously won't actually work if booted.

Any objections?

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

Thanks, I will commit that change.

When we were developing devLib we noted that linkers see a difference between

  devLibVME *pdevLibVME = NULL;

and

  devLibVME *pdevLibVME;

The latter is better because you can link the second compiled definition with another object file that contains

  devLibVME *pdevLibVME = { ... };

whereas using the first definition the linker could object to the redefinition. Not sure if that's still the case, but it's good to be aware of the deliberate difference. The only place we have the first one is in the cygwin32 implementation, which will never talk to a real VMEbus.

Revision history for this message
mdavidsaver (mdavidsaver) wrote :

> a difference

This smells like UB. From the C/C++ prospective, both are strong symbols. Of course there is a practical difference of .bss vs. .data sections. It's news to me that any linker can be relied upon to silently merge two strong symbols if one is in .bss . Seems like this should be an error.

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

No UB, omitting the initializer makes it a tentative definition, which will be merged with any explicit definition found in another translation unit. See "Tentative definitions" in https://en.cppreference.com/w/c/language/extern

Revision history for this message
mdavidsaver (mdavidsaver) wrote :

Though I don't think it has any effect on the proposed changed, I'd like to clarify my confusion.

I don't see anything on this page about "another translation unit". In fact I see:

> If there are no definitions in the same translation unit, then the tentative definition acts as an actual definition with the initializer = 0 (or, for array, structure, and union types, = {0}).

In fact the GCC docs for -fno-common state:

> Unix C compilers have traditionally allocated storage for uninitialized global variables
> in a common block. This allows the linker to resolve all tentative definitions of the
> same variable in different compilation units to the same object, or to a non-tentative
> definition. This is the behavior specified by -fcommon, and is the default for GCC on
> most targets. On the other hand, this behavior is not required by ISO C, and on some
> targets may carry a speed or code size penalty on variable references.

https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.