// @(#)rtems-ctor.cc 1.6 - 95/04/25 // // /* * rtems-ctor.cc * * Description: * This file exists solely to (try to) ensure RTEMS is initialized * before any global constructors are run. * * The problem: * Global constructors might reasonably expect that new() will * work, but since new() uses malloc() which uses RTEMS regions, * it can not be called until after initialize_executive(). * * Global constructors are called in GNU systems one of 2 ways: * * an "invisible" call to __main() inserted by compiler * This __main() calls __do_global_ctors() which * walks thru the table and calls all global * constructors. * * or - * A special section is put into the linked binary. The * system startup code knows to run the constructors in * this special section before calling main(). * * By making RTEMS initialization a constructor, we avoid having * too much about all this. All we have to guarantee is that * this constructor is the first one run. * * * So for the first case above, this is what happens * * host crt0 * main() * __main() * __do_global_ctors() * bsp_start() * init_executive_early() * <> * * init_executive_late() * bsp_cleanup() * * TODO: * */ #include #include #include /* * RTEMS program name * Probably not used by anyone, but it is nice to have it. * Actually the UNIX version of CPU_INVOKE_DEBUGGER will probably * need to use it */ char *rtems_progname; class RTEMS { public: RTEMS(); ~RTEMS(); }; RTEMS rtems_constructor; RTEMS::RTEMS() { bsp_start(); } RTEMS::~RTEMS() { bsp_cleanup(); } extern "C" { int main(int argc, char **argv, char **environp) { rtems_argc = argc; rtems_argv = argv; rtems_envp = environp; if ((argc > 0) && argv && argv[0]) rtems_progname = argv[0]; else rtems_progname = "RTEMS"; /* * Start multitasking */ rtems_initialize_executive_late( bsp_isr_level ); /* * Returns when multitasking is stopped * This allows our destructors to get run normally */ fflush( stdout ); fflush( stderr ); return 0; } }