[Fwd: Re: feedback requested on proposed new directive]
Charles-Antoine Gauthier
charles.gauthier at nrc.ca
Wed Aug 30 14:44:33 UTC 2000
Joel Sherrill wrote:
>
> Rosimildo da Silva wrote:
> >
> > From: Charles-Antoine Gauthier <charles.gauthier at nrc.ca>
> > To: rtems-users <rtems-users at oarcorp.com>
> > Sent: Tuesday, August 29, 2000 11:07 AM
> > Subject: Re: [Fwd: Re: feedback requested on proposed new directive]
> >
> > >
> > > Yes yes yes! Do get rid of main in the startup code.
> >
> > We all know that the main() function used by RTEMS' startup
> > is a major pain. I am ready to celebrate with six pack beer
> > when it goes away. :-)
>
> I can certainly agree that finding the magic sequence of initialization
> that satisfies main(), RTEMS, device drivers, etc has certainly
> been an ongoing challenge. :)
>
> > > > Why not call main() from within the init_task ?
> > > > Global Ctor would be called from inside this init task.
> > >
> > > But this is a change in semantics. It requires that there be only one
> > > init task for all APIs In fact, it removes the need for applications to
> > > supply init tasks, unless the application supplied init tasks are just
> > > created automatically by the new RTEMS-supplied init task, the one you
> > > call init_task.
> >
> > Well, I do not think and changes much.
> > Why applications should supply init_tasks, anyway. ???
>
> Tradition.... Tradition... How did this tradition get started?
> I'll tell you... I don't know.
>
> <apologies to Fiddler on the Roof :)>
I certainly do not object to having an RTEMS-supplied init task. In
fact, I welcome it. BUT, there is a possible change in the semantics of
RTEMS, depending on what is done. The change does not affect me very
much given that I have no applications with more than one init task.
Still, the "contract" is there between the system and the programmers.
If you remove the ability to have multiple tasks started up
automatically, you might break some existing programs. One way to
maintain compatibility is to have the initialization task process the
list of user-supplied init tasks, create them and start them. I don't
see that this changes anything in the behavior of the system.
Mind you, I always found the pSOS-style init tasks a bit of a kludge. We
never did things that way in Harmony, our own in-house RTEMS. In
Harmony, the user supplied one task (guess what, it was the one with the
C main function). This task was started automatically AFTER some
essential system servers came to life, and it was responsible for
instantiating any other tasks the application required, including any
user-selectable servers.
But Harmony also had different semantics. Tasks where organized in a
parent/child hierarchy, and killing a task also killed all of its
offsprings (as well as recovering all memory malloc'ed by the dying
tasks). The main task was the parent of all application tasks. Killing
it shut down the application. To make this single rooted parent/child
tree work, there had to be a single main task for all processors in the
system (and yes, all tasks where global objects by nature).
Given that neither pSOS, ORKID, nor RTEMS has this parent/child
relationship, it is acceptable to instantiate multiple tasks out of the
blue, although I won't fight to maintain this capability.
>
> > >From a programmer standpoint, I expect the system to call my application
> > entry point, main(), and I'll do the initialization of my specific tasks
> > from there.
> > Just like Linux, WIndows, OS/2, DOS, ( put your OS here ).
> >
> > The init_task() should be some kind of "super duper task". It is a RTEMS,
> > POSIX, iTron task at same the time. It should work with any API.
>
> OK.. I'll bite. :)
>
> Every task is capable of using any API. But I understand your meaning...
>
> We probably should borrow an idea I worked out for GNAT/RTEMS. There is
> an RTEMS init task (API flavor is irrelevant). It does whatever it
> takes to initialize things before calling "Ada main". What about
> something like this?
>
> rtems_task Init()
> {
> int status;
>
> #if defined(GET_ARGS)
> gets(cmdline);
> parse cmdline into argc, argv
> #endif
> #if defined(MOUNT_REAL_DISKS)
> initialize disk based filesystems
> #endif
> #if defined(HAS_NETWORKING)
> initialize networking
> #endif
>
/* My point is that you should have this for backward compatibility
*/
create_and_start_user_supplied_init_tasks();
> status = main( argc, argv, environp );
> exit( status );
> }
>
> As time goes on, I can see other initialization that would have to be
> inserted
> before main() -- network initialization is already there. Mounting
> a real disk filesystem would be another.
>
> [I can easily see a way to instantiate this code via something like
> confdefs.h.]
>
> > > > start ---> boot_card() ----> start multi-task --> init_task() -->
> > > > init()/fini()
>
> Would init()/fini() get called in these cases if main were at the
> application level?
>
> Given the above scheme it would if USE_INIT_FINI were defined in bsp.h.
>
> > > >
> > > I am wondering if we need to register the exception tables earlier that
> > > this? In which case, we must re-implement to functionality of _init to
> > > call the __register_frame_info earlier, and call __do_global_ctors once
> > > multitasking has started up.
> > >
> > > If you don't call __register_frame_info early, then no user supplied
> > > initialization code should throw an exception. This may not be a
> > > significant limitation, but it should be documented.
> > >
> >
> > I do not think that any user code would run until the main() is called....
> > so we might be ok.
Actually, the device driver initialization functions run before. These
can definitely be user code.
>
> One minor gotcha is that NO C++/Ada/Java? code should run until after
> main().
I think that your limitation is too strong, but certainly safe. I think
the real issue is that device drivers written in C++/Ada/Java cannot
throw exceptions during initialization. This looks to me somewhat like
an artificial constraint given that the solution appears relatively
simple: call __register_frame_info before initializing the device
drivers.
Now the only limitation is that device driver initialization cannot
create threads, unless you move the device driver initialization into
the init task... If you do this, then you could call _init at the start
of the init task.
>
> > > Yes, but now one must ask: where does argc and argv come from? This is
> > > an issue for me at this time. We got dejagnu working and have managed to
> > > run most of the libgcj regression testsuite on our targets. Except that
> > > it looks like the mauve test executables expect arguments. Doh! I should
> > > I get these arguments into the target? I have several possibilities in
> > > mind, but I would like to see RTEMS implement some documented approaches
> > > to do this. I could then code up the one that makes the most sense into
> > > the expect scripts.
> > >
> >
> > It could be provided along with the main() function. The init_task
> > would use the global values. If you do not provide them, along with
> > your main() function, the link would use the module in the library
> > with the default values.
> >
> > /* default_args.c */
> > char *global_argv[] =
> > {
> > "rtems"
> > };
> > int global_argc = sizeof( global_argv ) / sizeof( global_argv[ 0 ] ) ;
> > /* end default_args.c */
> >
> > int main( int argc, char **argv )
> > {
> >
> > }
>
> One of the network demos (ttcp?) has code to convert a string into an
> argc/argv
> type arrangement. Then the "ttcp_main" is invoked with them. The
> example above
> I hacked would call that code.
>
> > Rosimildo.
>
> --
> Joel Sherrill, Ph.D. Director of Research & Development
> joel at OARcorp.com On-Line Applications Research
> Ask me about RTEMS: a free RTOS Huntsville AL 35805
> Support Available (256) 722-9985
--
Charles-Antoine Gauthier
Institute for Information Technology Institut de technologie de
l'information
National Research Council of Canada Conseil national de recherches du
Canada
More information about the users
mailing list