[riot-devel] RIOT and static initializers in C++

Ludwig Ortmann ludwig.ortmann at fu-berlin.de
Sat Sep 20 22:13:15 CEST 2014


Hi all,

Great work!
I never got around to fully understand the startup sequence internals (I looked into it a bit because the current  implementation also had problems in an older FreeBSD release but then the infection went away with the next release..) and it sounds like this is a fine solution.
Will you open a pull request?

Cheers, Ludwig

On 20. September 2014 20:49:31 MESZ, DangNhat PhamHuu <phamhuudangnhat at gmail.com> wrote:
>Hi Hiesgen, Raphael,
>Thanks for sharing for finding with us :-)
>
>Currently, on native port, a RIOT program will be started like this
>(some details are omitted):
>(default internal linker script is used in native port)
>Loader loaded program to memory
>→ call _start → call libc_start_main → call libc_csu_init
>                                                            → call
>main (will never be called like normal startup sequences in RIOT)
>
>In __libc_csu_init , it will call the contructor functions which are
>placed in __init_array table just like normal startup sequence for
>Linux programs ([1]). In this table ( __init_array ) we have the RIOT
>startup code and the code for C++ static initialization.
>As we can see that in normal startup sequence, all functions in
>__init_array will be executed before branching to main, but in RIOT,
>RIOT’s startup code will never return after it has been called in
>__libc_csu_init (RIOT’s startup code then init the kernel and create
>the main thread with our application).
>Unfortunately, gcc will placed constructor functions to __init_array
>table in the order of their declarations. Thus, static initialization
>for bar is placed after RIOT’s startup code and will never been
>called.
>To work around with this we can put the priority (101 to 65535, lower
>is higher priority) for these constructor functions (in
>/cpu/native/startup.c and our main.cpp) like this. [2] [3]
>
>diff --git a/cpu/native/startup.c b/cpu/native/startup.c
>index 88004aa..605de99 100644
>--- a/cpu/native/startup.c
>+++ b/cpu/native/startup.c
>@@ -192,7 +192,7 @@ The order of command line arguments matters.\n");
>
> }
>
>-  __attribute__((constructor)) static void startup(int argc, char
>**argv)
>+  __attribute__((constructor (65535))) static void startup(int argc,
>char **argv)
> {
>     _native_init_syscalls();
>
>#include "stdio.h"
>
>using namespace std;
>
>struct foo {
>  foo() : data(1) { }
>  int data;
>};
>
>static foo bar __attribute__ ((init_priority (101)));
>
>int main() {
>  printf("%d\n", bar.data);
>}
>
>Then you will see the static initialization has been called and 1 will
>be printed.
>As I haven’t found better solution for now, so it’s just a workaround
>to make thing works.
>
>For some other platforms such as arm-based ones (iot-lab_M3, etc.),
>RIOT has provided the linker script with init_array section and
>startup code with libc_init_array function. Therefore, C++ static
>initialization can be used when C++ support has been provided for
>these platforms.
>
>P/S: please don’t use <iostream> but use <cstdio> instead as
>currently, we don’t support some C++ headers like this [4].
>
>[1]
>http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html
>[2] https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
>[3]
>https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html#C_002b_002b-Attributes
>[4] https://github.com/RIOT-OS/RIOT/wiki/Using-CPP-on-RIOT
>_______________________________________________
>devel mailing list
>devel at riot-os.org
>http://lists.riot-os.org/mailman/listinfo/devel



More information about the devel mailing list