#2408 closed enhancement (fixed)

Linker set based initialization

Reported by: Sebastian Huber Owned by: Sebastian Huber
Priority: normal Milestone: 5.1
Component: unspecified Version: 4.10
Severity: normal Keywords:
Cc: Blocked By:
Blocking:

Description

Linker sets are used for example in Linux, FreeBSD (they are used in the RTEMS port of the FreeBSD network stack, e.g. libbsd), eCos and for global C++ constructors. They provide a space efficient and flexible means to initialize modules. A linker set consists of

  • dedicated input sections for the linker (e.g. .ctors and .ctors.* in the case of global constructors),
  • a begin marker (e.g. provided by crtbegin.o, and
  • an end marker (e.g. provided by ctrend.o).

A module may place a certain data item into the dedicated input section. The linker will collect all such data items in this section and creates a begin and end marker. The initialization code can then use the begin and end markers to find all the collected data items (e.g. function pointers).

Lets look how this works using a simple example. For this we need three files myset.h,

#ifndef MYSET_H
#define MYSET_H

/* The linker set items */
typedef struct {
  void (*func)(void);
} item;

/*
 * Macro to create a linker set item.  The first parameter is
 * the designator of the item.  It must be unique within the
 * module scope.  The second parameter is the desired function.
 */
#define MYSET_ITEM(i, f) \
    __attribute__((used)) \
    __attribute__((section(".rtemsroset.myset.content"))) \
    static item i = { f }

#endif /* MYSET_H */

module.c

#include "myset.h"
#include <stdio.h>

/*
 * Some global function that needs a module specific
 * intialization done by f().
 */
void
g(void)
{

        printf("g()\n");
}

/* The module constructor */
static void
f(void)
{

        printf("f()\n");
}

/*
 * This registers the module constructor f()
 * in the linker set "myset".
 */
MYSET_ITEM(i, &f);

and init.c.

#include "myset.h"
#include <stddef.h>

/* Should be in a proper header file */
void g(void);

/* Define the start marker */
__attribute__((used))
__attribute__((section(".rtemsroset.myset.begin")))
static volatile const item begin[0];

/* Define the end marker */
__attribute__((used))
__attribute__((section(".rtemsroset.myset.end")))
static volatile const item end[0];

int main(void)
{
        size_t n = &end[0] - &begin[0];
        size_t i;

        /* Call all functions of the linker set */
        for (i = 0; i < n; ++i) {
                (*begin[i].func)();
        }

        /*
         * This will pull in the module.c and register its item in the
         * linker set "myset".  So g() can rely on f() being called first.
         */
        g();

        return (0);
}

In the linker command file of the GNU linker we need the following statement.

.rtemsroset : {
	KEEP (*(SORT(.rtemsroset.*)))

The KEEP() ensures that a garbage collection by the linker will not discard the content of this section. This would be normally the case since the linker set items are not referenced directly. The SORT() directive sorts the input sections lexicographically. Please note the lexicographical order of the .begin, .content and .end section name parts in the previous example which ensures that the position of the begin and end markers are right. The interesting part of linker map file of the previous example may look like this.

.rtemsroset     0x0000000001001990        0x4 load address 0x000000000002268c
 *(SORT(.rtemsroset.*))
 .rtemsroset.myset.begin
                0x0000000001001990        0x0 init.o
 .rtemsroset.myset.content
                0x0000000001001990        0x4 module.o
 .rtemsroset.myset.end
                0x0000000001001994        0x0 init.o

So what is the benefit of using linker sets to initialize modules? Currently in RTEMS all available managers (semaphore, message queue, barrier, etc.) are initialized since the initialization code doesn't know what is actually used by the application. With the linker set approach we need to initialize only those managers that are used by the application. In case an application uses message queues, then it must call rtems_message_queue_create(). In the module implementing this function we can place a linker set item and register the message queue handler constructor. Otherwise, in case the application doesn't use message queues, then there will be no reference to the rtems_message_queue_create() function and the constructor is not registered, thus nothing of the message queue handler will be in the final executable.

Change History (58)

comment:3 Changed on 12/08/15 at 12:53:24 by Sebastian Huber <sebastian.huber@…>

In b618d8cfc54f84d4ed03dc7b7fa510c872e6128a/rtems:

Add RTEMS linker sets

Update #2408.

comment:4 Changed on 12/09/15 at 07:00:51 by Sebastian Huber

The POSIX API is disabled in 4.9 and 4.10. In 4.11 and 4.12 sizes are
presented with POSIX enabled/disabled. The 4.12 without prefix is with the
linker set based initialization. In 4.12 the Newlib internal locks are
enabled.12. The PNOLS version is with POSIX enabled and the old initialization
infrastructure.

Executable sizes for the SPARC/SIS ticker.exe.

Text Data BSS Workspace Non-Text
4.9 80384 2532 2996 51432 56960
4.10 124384 1828 2384 51056 55268
4.11 100592 1616 7008 44120 52744
4.11/POSIX 104608 1760 8528 45200 55488
4.12/PNOLS 105296 1872 8512 45376 55760
4.12/POSIX 101680 1808 6592 45336 53736
4.12 101472 1808 6528 44336 52672

The huge increase in the test size from 4.9 to 4.10 is mostly due to the
introduction of the pipe() support which pulls in sprintf().

The increase of the BSS section from 4.10 to 4.11 is due to the static
initialization of the scheduler data structures (move from workspace to BSS).

Executable sizes for the SPARC/SIS minimum.exe.

Text Data BSS Workspace Non-Text
4.9 45808 2324 2708 3288 8320
4.10 30032 1300 1296 3240 5836
4.11 34032 320 2976 2000 5296
4.11/POSIX 41664 1168 4480 2216 7864
4.12/PNOLS 39904 1232 4480 2136 7848
4.12/POSIX 29104 272 2304 2128 4704
4.12 28976 272 2240 1928 4440
Last edited on 01/27/16 at 14:52:05 by Sebastian Huber (previous) (diff)

comment:5 Changed on 12/10/15 at 07:33:58 by Sebastian Huber <sebastian.huber@…>

In 2858939a2ccb3cf1918dadd9cda1fd1d8ab5a9ef/rtems:

bsps: Delete superfluous bsp_pretasking_hook()

Use the bsp_predriver_hook() instead.

Update #2408.

comment:7 Changed on 01/26/16 at 17:04:55 by Sebastian Huber

Owner: set to Sebastian Huber
Status: newassigned

comment:8 Changed on 02/03/16 at 09:29:51 by Sebastian Huber <sebastian.huber@…>

In 36b86d7eb5e51a62c0cee1906210b389c2ab96eb/rtems:

score: Create idle threads via linker set

This allows a more fine grained rtems_initialize_data_structures().

Update #2408.

comment:9 Changed on 02/03/16 at 09:30:01 by Sebastian Huber <sebastian.huber@…>

In a853c8518d7b8ccf54491018857ed86548f3ea24/rtems:

Optional Initial Extensions initialization

Update #2408.

comment:10 Changed on 02/03/16 at 09:30:14 by Sebastian Huber <sebastian.huber@…>

In 92bb345374ea3982b40b10e7d50ecfc1cb4d2ed3/rtems:

Optional Extensions initialization

Update #2408.

comment:11 Changed on 02/03/16 at 09:30:24 by Sebastian Huber <sebastian.huber@…>

In 565672a257156f78295608afb05157d1c7da7000/rtems:

Optional Classic Tasks initialization

Update #2408.

comment:12 Changed on 02/03/16 at 09:30:35 by Sebastian Huber <sebastian.huber@…>

In 26335844f484c8cd061444cebba9480b62d165cb/rtems:

Optional Classic Timer initialization

Update #2408.

comment:13 Changed on 02/03/16 at 09:30:46 by Sebastian Huber <sebastian.huber@…>

In a7f36829c08d86f6a53b5aad83a21e38aa1454b5/rtems:

Optional Classic Signal initialization

Update #2408.

comment:14 Changed on 02/03/16 at 09:30:57 by Sebastian Huber <sebastian.huber@…>

In ae85b0663eb19db435476d268a10187633f2ba56/rtems:

Optional Classic Event initialization

Update #2408.

comment:15 Changed on 02/03/16 at 09:31:07 by Sebastian Huber <sebastian.huber@…>

In ed8b00e667fe179730beb8947b5afb6bcc234d7a/rtems:

Optional Classic Message Queue initialization

Update #2408.

comment:16 Changed on 02/03/16 at 09:31:18 by Sebastian Huber <sebastian.huber@…>

In cbaac1f7f4b3d78673abfde9bd6ed7e43dddf12c/rtems:

Optional Classic Semaphore initialization

Update #2408.

comment:17 Changed on 02/03/16 at 09:31:28 by Sebastian Huber <sebastian.huber@…>

In fd3cc36f61e5b92b2234ff5eff5250f0ce6447bb/rtems:

Optional Classic Partition initialization

Update #2408.

comment:18 Changed on 02/03/16 at 09:31:39 by Sebastian Huber <sebastian.huber@…>

In 365456cce3f3cf6da8a1bab9199e4bbd5f240dde/rtems:

Optional Classic Region initialization

Update #2408.

comment:19 Changed on 02/03/16 at 09:31:50 by Sebastian Huber <sebastian.huber@…>

In af12278f9b33d7d8dca96d3873472ef2382f3c8e/rtems:

Optional Classic Dual-Ported Memory initialization

Update #2408.

comment:20 Changed on 02/03/16 at 09:32:00 by Sebastian Huber <sebastian.huber@…>

In b377e3f6b70b5a5a09ac1dd77a450e4e5812cc42/rtems:

Optional Classic Rate Monotonic initialization

Update #2408.

comment:21 Changed on 02/03/16 at 09:32:11 by Sebastian Huber <sebastian.huber@…>

In 97d94ff3e96c86d2a23b26efe48a9386c16a915a/rtems:

Optional Classic Barrier initialization

Update #2408.

comment:22 Changed on 02/03/16 at 09:32:32 by Sebastian Huber <sebastian.huber@…>

In 04436ae7d83825300df85cabc3953f9c0314fe72/rtems:

Optional POSIX Signals initialization

Update #2408.

comment:23 Changed on 02/03/16 at 09:32:42 by Sebastian Huber <sebastian.huber@…>

In ef1a985fc7591988ef956dd7b35f9533bace68a6/rtems:

Optional POSIX Threads initialization

Update #2408.

comment:24 Changed on 02/03/16 at 09:32:53 by Sebastian Huber <sebastian.huber@…>

In cef56750eb5ce8a2aa31ff4e3bc038bc656a0d96/rtems:

Optional POSIX Cleanup initialization

Update #2408.

comment:25 Changed on 02/03/16 at 09:33:04 by Sebastian Huber <sebastian.huber@…>

In f4fee4778e9ab8a61c00fdb34a6d2e49f2e0b2ce/rtems:

Optional POSIX Condition Variable initialization

Update #2408.

comment:26 Changed on 02/03/16 at 09:33:14 by Sebastian Huber <sebastian.huber@…>

In 9871f5dc60c622b58710f624f2ddb9328de16eb8/rtems:

Optional POSIX Mutex initialization

Update #2408.

comment:27 Changed on 02/03/16 at 09:33:25 by Sebastian Huber <sebastian.huber@…>

In 3015ed641a41059dec9abad1eb3872a006ee6324/rtems:

Optional POSIX Message Queue initialization

Update #2408.

comment:28 Changed on 02/03/16 at 09:33:36 by Sebastian Huber <sebastian.huber@…>

In 2189b3e963f7e43e9fc577ab4f24c952cef5b08e/rtems:

Optional POSIX Semaphore initialization

Update #2408.

comment:29 Changed on 02/03/16 at 09:33:46 by Sebastian Huber <sebastian.huber@…>

In 6c678557906cbbe73af1691e90e52911b2d00223/rtems:

Optional POSIX Timer initialization

Update #2408.

comment:30 Changed on 02/03/16 at 09:33:57 by Sebastian Huber <sebastian.huber@…>

In e4e7f149c0f4d167a40862fee90707d38ee1aaf6/rtems:

Optional POSIX Barrier initialization

Update #2408.

comment:31 Changed on 02/03/16 at 09:34:07 by Sebastian Huber <sebastian.huber@…>

In 76a8328945bdefafc255d9589d4dcc371e1a73ef/rtems:

Optional POSIX RWLock initialization

Update #2408.

comment:32 Changed on 02/03/16 at 09:34:18 by Sebastian Huber <sebastian.huber@…>

In 4eee8781458f271be78e6f92cf344f9dbd2b4c8e/rtems:

Optional POSIX Spinlock initialization

Update #2408.

comment:33 Changed on 02/03/16 at 09:34:29 by Sebastian Huber <sebastian.huber@…>

In 190169fee2f267f5e32813eb6fd3e9b51430effc/rtems:

Optional CPU Set Handler initialization

Update #2408.

comment:34 Changed on 02/03/16 at 09:34:39 by Sebastian Huber <sebastian.huber@…>

In 2605a48938b9b3466add326d8e94b9622ffad7ba/rtems:

Optional POSIX Keys initialization

Update #2408.

comment:35 Changed on 02/03/16 at 09:35:01 by Sebastian Huber <sebastian.huber@…>

In 3d36164fe5a366cf206ed3d2e8dc5b4d9e366c14/rtems:

Use linker set for root file system initialization

Update #2408.

comment:36 Changed on 02/03/16 at 09:35:22 by Sebastian Huber <sebastian.huber@…>

In ca4602e914d4ec00bf5db51e0830d702d5bc3f4e/rtems:

Use linker set for libio initialization

Update #2408.

comment:37 Changed on 02/03/16 at 09:35:33 by Sebastian Huber <sebastian.huber@…>

In 6bf44a581b35aba967034bc3e0348a4d1f36a048/rtems:

Use linker set for driver manager initialization

Update #2408.

comment:38 Changed on 02/03/16 at 09:35:44 by Sebastian Huber <sebastian.huber@…>

In 8ca372e9b47319a034a32250e037247e5b3c4c9e/rtems:

Use linker set for MPCI initialization

Update #2408.

comment:39 Changed on 02/03/16 at 09:35:55 by Sebastian Huber <sebastian.huber@…>

In 1ff8eca17a9f09bad3ab50c640547916808bf085/rtems:

Use linker set for Classic User Tasks init

Update #2408.

comment:40 Changed on 02/03/16 at 09:36:06 by Sebastian Huber <sebastian.huber@…>

In 4210114032d8d079bddaa2333875c38e30c93490/rtems:

Use linker set for POSIX User Threads init

Update #2408.

comment:41 Changed on 02/03/16 at 09:38:47 by Sebastian Huber

Implementation is complete. Documentation is missing.

comment:42 Changed on 02/04/16 at 11:59:09 by Sebastian Huber

Status: assignedaccepted

comment:43 Changed on 03/01/16 at 14:01:44 by Sebastian Huber <sebastian.huber@…>

In 1db95677debcd5497006d04b70634464a332a95b/rtems:

sptests/spsysinit01: Fix for RTEMS_DEBUG

Update #2408.

comment:44 Changed on 03/11/16 at 00:13:28 by Joel Sherrill

Just checking. Is this ready to close or do you have additional plans?

comment:45 Changed on 03/14/16 at 07:16:20 by Sebastian Huber

Documentation is incomplete.

comment:46 Changed on 10/12/16 at 09:13:53 by Sebastian Huber <sebastian.huber@…>

In be573185e6d6ddafdd3612c7c2db04aa0f65a330/rtems:

score: More robust linker sets

Update #2408.
Update #2790.

comment:47 Changed on 11/14/16 at 16:38:08 by Joel Sherrill

Should this ticket be closed now?

comment:48 Changed on 11/15/16 at 06:05:10 by Sebastian Huber

No, documentation is still incomplete. I am not satisfied with the GCC 7 support.

comment:49 Changed on 12/06/16 at 11:03:23 by Sebastian Huber <sebastian.huber@…>

In 4b579c5f5170e1fb6a0573729444c289643b7d84/rtems:

score: Simplify linker set API

Resurrect RTEMS_LINKER_SET_BEGIN() and RTEMS_LINKER_SET_END().

Add new macros RTEMS_LINKER_SET_ITEM_COUNT(),
RTEMS_LINKER_SET_IS_EMPTY(), and
RTEMS_LINKER_SET_FOREACH().

Remove confusing RTEMS_LINKER_SET_ASSIGN_BEGIN() and
RTEMS_LINKER_SET_ASSIGN_END().

Fix RTEMS_LINKER_SET_SIZE() to return the size in characters as
specified by the documentation.

Update #2408.
Update #2790.

comment:50 Changed on 12/07/16 at 04:10:42 by Chris Johns

Jeff has reported to me libbsd is broken.

comment:51 Changed on 12/12/16 at 07:09:08 by Sebastian Huber

Resolution: fixed
Status: acceptedclosed

Documentation complete.

comment:52 Changed on 05/11/17 at 07:31:02 by Sebastian Huber

Milestone: 4.124.12.0

comment:53 Changed on 11/09/17 at 06:27:14 by Sebastian Huber

Milestone: 4.12.05.1

Milestone renamed

comment:54 Changed on 04/20/18 at 13:25:21 by Sebastian Huber <sebastian.huber@…>

In 6d21a3f2/rtems:

drvmgr: Remove bsp_driver_level_hook()

Use RTEMS_SYSINIT_ITEM() instead.

Update #2408.

comment:55 Changed on 04/20/18 at 13:25:54 by Sebastian Huber <sebastian.huber@…>

In c4ccf26c/rtems:

bsps: Convert all bsp_predriver_hook()

Use RTEMS_SYSINIT_ITEM() instead.

Update #2408.

comment:56 Changed on 01/02/20 at 08:49:16 by Sebastian Huber <sebastian.huber@…>

In 453bb4b/rtems:

rtems: Fix MPCI initialization

Update #2408.

comment:57 Changed on 02/04/20 at 06:22:23 by Sebastian Huber <sebastian.huber@…>

In 813ada5/rtems-docs:

c-user: Update system initialization chapter

Update #2408.
Update #3838.

comment:58 Changed on 02/06/20 at 14:24:21 by Sebastian Huber <sebastian.huber@…>

In a4b23d9/rtems-docs:

c-user: Document new linker set macros

Adjust copyright. Linker sets were introduced in 2015.

Update #2408.
Close #3865.

Note: See TracTickets for help on using tickets.