Use weak functions in the RTEMS core?

Jonathan Brandmeyer jbrandmeyer at planetiq.com
Thu Apr 9 15:53:46 UTC 2020


On Thu, Apr 9, 2020 at 9:25 AM Gedare Bloom <gedare at rtems.org> wrote:

> On Wed, Apr 8, 2020 at 10:53 PM Sebastian Huber
> <sebastian.huber at embedded-brains.de> wrote:
> >
> > On 09/04/2020 03:32, Chris Johns wrote:
> >
> > > On 2020-04-09 03:43, Sebastian Huber wrote:
> > >> On 08/04/2020 19:34, Jonathan Brandmeyer wrote:
> > >>> Instead of treating weak references as a single level of
> > >>> indirection, I think you have to treat them as a single overridable
> > >>> interface.  In a dynamically-linked application, we might try to
> > >>> perform an override using the LD_PRELOAD feature. But in a
> > >>> statically-linked application we have to do it differently.  The
> > >>> overriding archive must be named in full, and it must be named as an
> > >>> object to be linked instead of a library to be searched.
> > >>> Furthermore, an interface can have only one override that ends up in
> > >>> the linked application.
> > >> Yes, you can only have one strong implementation, otherwise you get
> > >> multiple definition errors.
> > >
> > > I have only ever considered weak references as an overridable
> > > interface within a user's application and not layered within RTEMS
> > > itself. I am not sure about automatic indirection within an archive.
> > Yes, this is one use case. You could use also a normal function in a
> > separate file to get something similar.
> > >
> > > In the case of different heap allocators why not have confdefs.h
> > > select the one we want and manage the indirection with a const table
> > > of pointers?
> >
> > Yes it can be done with new configuration options, however, this would
> > be my least favorite choice. I created an example how I would like to
> > use weak functions:
>

>
> > https://lists.rtems.org/pipermail/devel/2020-April/059196.html
> >
> Thanks for the code example it was helpful to me. What I understood is
> that:
> 1) An internal interface may be declared weakly aliased in RTEMS.
> 2) Implementations each need to go to a different file.
>     * Not clear to me if there can be more than 2: 1 weak, 1 strong?
>

In the linked application, there will be exactly one implementation.  You
can provide objects with as many strong implementations as you like, as
long as there is a clear way to distinguish between them at link time.

In this specific example, Mr. Huber lead off with the use of a trivial heap
definition: Malloc bumps pointers in a pool, and free does nothing.  The
other extreme might be a port of jemalloc to RTEMS.  You could implement
this with the following layout:

librtemsbsp.a provides the default RTEMS heap.  IIRC it's a single-threaded
first-fit search with deferred coalescing.  It provides weak references for
all of the heap functions: malloc, calloc, posix_memalign, and so on.  Some
of them can be defined in terms of the more general versions.  Instead of
hiding that fact as implementation details, they are explicitly documented
as such.  That way if someone wants to provide an override for the heap,
they know exactly which portions must be replaced, and which portions may
be left as their defaults.

librtems-heap-trivial.a is scoped to provide overrides of the particular
functions that it wishes to make strong, and no others.  It can probably
get away with using the default implementations of calloc and
posix_memalign.

librtems-heap-jemalloc.a does the same thing.  IIRC, it has some special
paths set aside for aligned allocation requests, so it would also override
the default definition of posix_memalign.

All of the heap overriders provide pkg-config files that name the full path
to their archives explicitly.  Ie, `pkg-config --libs rtems-heap-trivial`
would emit "/rtems_root/target_pair/lib/librtems-heap-trivial.a" instead of
"-lrtems-heap-trivial".  Users are explicitly told about this override
point, and that --libs should really be treated more like --objs if such an
option exists.

Luxury improvement: Teach pkg-config about an --objs flag.


> 3) A strong implementation may be pulled in by invoking a different,
>     non-aliased function implemented in the same file as (one of) the
>     strong implementations.
>

A strong implementation may be pulled in by linking one explicitly.  The
source of the reference is irrelevant.  There can be as many strong
implementations as you like, but mixing both strong and weak
implementations in the same archive is not allowed.


>
> Am I understanding this? I tried to map this to something in OOP but
> the abstraction failed somewhere in my cortex. It is almost like an
> interface class where you can instantiate objects of only one of the
> implementations.
>

The closest example I can think of is the use of mock objects.  The
difference is that the linker is performing the injection and it is for the
entire linked program instead of on a per-test basis.


> I am a little concerned that the approach is fragile still, based on
> the discussion about how weak aliases may be resolved dependent upon
> link order in command lines, etc.
>

I don't think there's any way around this.  If you are using weak symbols,
the final link state will depend on the order that the linker sees the
definitions.

-- 
Jonathan Brandmeyer
PlanetiQ
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rtems.org/pipermail/devel/attachments/20200409/e90d9acd/attachment.html>


More information about the devel mailing list