To sum up all your questions: vxWorks ain't like Unix.
vxWorks doesn't have the concept of separate "programs" with
separate address spaces, and separate global variables. There is
only one address space--and when you load new modules with ld(),
the global variables in that module are added to that address space.
> 1. Why can't we use main function with C language?
>
> When we programmed some applications with main function, We couldn't
> download those applications. Undefined symbol (__eabi) error occurred.
Lemme guess. PowerPC, right? :)
Including main() causes the compiler/linker to automagically link in a
bunch of Other Stuff. In Unix, including main() causes prologue code
(which initializes the C standard library) to run, etc. In C++, this
prologue code initializes static constructors.
vxWorks on the powerPC, on the other hand, corresponds to a
specification
called EABI (Embedded Application Binary Interface); which calls for a
function __eabi to be invoked when a program starts. This is, however,
Not What You Want in vxWorks.
The bottom line: don't call anything main().
> 2. In tornado shell, we can't execute some programs many times. All
> Those programs have global variables. So, After executing those
> programs, Global variables contain some values that are different from
> program startup values.
>
> How do we initialize all global variables on program startup?
Do so explicitly. The static initialization happens only once. For
those objects linked with the kernel, static initialization happens when
the system starts. If you use the dynamic loader, the initialization
happens when the module is loaded. However, "restarting" the program
does
not cause globals to be initialized.
Oh, and one more thing. The automatic cleanup that you get in Unix when
a program dies (all memory blocks freed, stdio flushed, all files
closed)
does NOT happen in vxWorks. You **MUST** free all resources you use
yourself.
> Why don't vxworks initialize global variables on program startup.
vxWorks views the entire system as a "program"; all the modules are part
of that program.
> When Initialization occurs? Object code downloading?
Globals defined in the module are initialized when you download the
module,
but at no time after. (Unless you unload the module and load it again;
this will ause them to be re-initialized).
> 3. On program exit, is dynamically allocated memory automatically freed?
Nope.
> Otherwise, we must free all dynamically allocated memory explicitly?
Yup.
> Thanks.
You're welcome.
:)
--
------------------------------------------------------------------------
engineer_scotty (no, not that one) -- consumer of fine ales and lagers
some days you're the fire hydrant, some days you're the dog | go blazers
no small furry creatures were harmed in the creation of this .signature
------------------------------------------------------------------------
1. Why can't we use main function with C language?
When we programmed some applications with main function, We couldn't
download those applications. Undefined symbol (__eabi) error occurred.
2. In tornado shell, we can't execute some programs many times. All
Those programs have global variables. So, After executing those
programs, Global variables contain some values that are different from
program startup values.
How do we initialize all global variables on program startup?
Why don't vxworks initialize global variables on program startup.
When Initialization occurs? Object code downloading?
3. On program exit, is dynamically allocated memory automatically freed?
Otherwise, we must free all dynamically allocated memory explicitly?
Thanks.
Do you inform me of EABI specification on VxWorks with MPC860 (PowerPC core)?
What you said is that All global variables initialization is executed by
programmer explicitly? dynamically allocated memory management,too ?
engineer_scotty wrote:
> Lee Dong Yul wrote:
> >
> > Hello, We are developing some programs on VxWorks OS.
>
> To sum up all your questions: vxWorks ain't like Unix.
>
> vxWorks doesn't have the concept of separate "programs" with
> separate address spaces, and separate global variables. There is
> only one address space--and when you load new modules with ld(),
> the global variables in that module are added to that address space.
>
> > 1. Why can't we use main function with C language?
> >
> > When we programmed some applications with main function, We couldn't
> > download those applications. Undefined symbol (__eabi) error occurred.
>
Yup; you can download it from Motorola's website. (Somewhere...the
website
is complicated, and I can't remember where. Start with
http://www.mot.com/SPS/PowerPC and look in the 821 section.)
> What you said is that All global variables initialization is executed by
> programmer explicitly? dynamically allocated memory management,too ?
What I meant was---if you want a module with global variables to be
restartable;
you had better explicitly initialize them.
Consider the following module:
/* foobar module #1 */
#include "stdio.h"
int foobar = 1;
void runFoobar(void) {
printf ("foobar is %d\n", foobar);
foobar++;
printf ("foobar is now %d\n", foobar):
}
/* end of foobar */
If you compile this and ld() it into vxWorks; the first time you type
runFoobar from the shell, you will get
>foobar is 1
>foobar is now 2
The second time you run it, you will get
>foobar is 2
>foobar is now 3
And so on.
If, on the other hand, you use
/* foobar module #2 */
#include "stdio.h"
int foobar;
void initFoobar(void) {
foobar = 1;
}
void runFoobar(void) {
initFoobar();
printf ("foobar is %d\n", foobar);
foobar++;
printf ("foobar is now %d\n", foobar):
}
/* end of foobar */
Then each invokation of runFoobar() produces the same result.
As far as memory management goes; it is initialized by your BSP. As
long as you
aren't working on the BSP, you don't have to do anything special to make
malloc()
work.
> engineer_scotty wrote:
>
> > Lee Dong Yul wrote:
> > >
> > > Hello, We are developing some programs on VxWorks OS.
> >
> > To sum up all your questions: vxWorks ain't like Unix.
> >
> > vxWorks doesn't have the concept of separate "programs" with
> > separate address spaces, and separate global variables. There is
> > only one address space--and when you load new modules with ld(),
> > the global variables in that module are added to that address space.
> >
> > > 1. Why can't we use main function with C language?
> > >
> > > When we programmed some applications with main function, We couldn't
> > > download those applications. Undefined symbol (__eabi) error occurred.
> >
> > Lemme guess. PowerPC, right? :)
> >
> > Including main() causes the compiler/linker to automagically link in a
> > bunch of Other Stuff. In Unix, including main() causes prologue code
> > (which initializes the C standard library) to run, etc. In C++, this
> > prologue code initializes static constructors.
> >
> > vxWorks on the powerPC, on the other hand, corresponds to a
> > specification
> > called EABI (Embedded Application Binary Interface); which calls for a
> > function __eabi to be invoked when a program starts. This is, however,
> > Not What You Want in vxWorks.
> >
> > The bottom line: don't call anything main().
--
This one's been covered pretty well... just use another name.
>2. In tornado shell, we can't execute some programs many times. All
>Those programs have global variables. So, After executing those
>programs, Global variables contain some values that are different from
>program startup values.
>How do we initialize all global variables on program startup?
>Why don't vxworks initialize global variables on program startup.
Think of VxWorks as one big continuously running program with multiple
threads (tasks). Global variables are not reinitialized just because
a task gets started. To get around this I've written initialization
modules for certain pieces of code that I want to be able to restart
like Unix programs, e.g. code ported from unix like editors and such.
The initialization module ensures that initialized variables and BSS
variables are set right, then branches to the (renamed) main function when
done. I've included an example copy below, although I use a separate slightly
customized init module for each such program.
>When Initialization occurs? Object code downloading?
Right.
>3. On program exit, is dynamically allocated memory automatically freed?
No. Good programmers clean up after themselves anyway.
So here's that init module. Link this with your PROGRAM. You call
PROGRAM_start() which in turn calls PROGRAM_main(). There's also another
little function that goes before this one that I haven't included
(called "PROGRAM()") which repackages arguments so that old unix code
expecting argv/argc stuff will work.
Good luck,
Georg
----------------------------- crt0.c ------------------------------
#include <vxWorks.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <moduleLib.h>
/*
* PROGRAM startup module.
*
* This version for VxWorks. The main purpose is to properly initialize the
* initialized data space and bss between different runs of PROGRAM. The first
* time it executes, this routine saves away the entire initialized data space
* in malloc'd memory. On subsequent runs it restores the initialized data.
* It zeroes the bss area as well, but *be warned* that this should not
* be relied upon. Some BSS variables (those labeled as "common") seem to
* be placed outside the normal BSS block by the VxWorks
* loader, therefore *never* depend on uninitialized variables to be
* automatically set to 0. Explicitly initialize them to zero instead.
*
* 97/09/17 Georg Feil Changed to use moduleLib for segment addresses,
* added clearing of BSS.
* 97/06/27 Georg Feil Converted from assembly to C (for PPC port).
* 91/04/23 Georg Feil Cleaned up, added comments.
* 90/07/26 Georg Feil Fixed stack creep problem at malloc() call.
* 90/06/27 Georg Feil Initial revision, from s2 dev system.
*/
/* flag shows whether initialized data area has been copied (!=0 means yes)
Value is start of malloc data area. */
static char* init=0;
void PROGRAM_start(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6,
int arg7, int arg8, int arg9, int arg10)
{
int PROGRAM_main(); /* define main() this way to soothe the compiler */
char* d0;
MODULE_ID mod_id;
MODULE_INFO mod_info;
/* get segment info from moduleLib (properly gets last instance loaded) */
mod_id=moduleFindByName("PROGRAM");
if (mod_id==NULL) {
printf("PROGRAM_start(): Error, could not find module named \"PROGRAM\"\n");
return;
}
if (moduleInfoGet(mod_id, &mod_info) == ERROR) {
printf("PROGRAM_start(): Error, could not get module info for ID 0x%lx\n",
(unsigned long)mod_id);
return;
}
/* clear uninitialized data area (bss) *** see warning in comment at top */
bzero(mod_info.segInfo.bssAddr, mod_info.segInfo.bssSize);
/* Copy initialized data area to save (1st time) or restore it (other times).
(gets copied after end of uninitialized data (bss))
Uses malloc() to obtain storage space -- Warning this is never freed. */
if (init==0) {
/* malloc() enough memory to hold initialized data region */
d0=malloc(mod_info.segInfo.dataSize);
if (d0==0) {
/* malloc() error (returned NULL), exit immediately */
printf("PROGRAM_start(): Error, could not malloc\n");
return;
}
init=d0; /* save malloc() address in init */
/* save initialized data */
bcopy(mod_info.segInfo.dataAddr, init, mod_info.segInfo.dataSize);
}
else {
/* restore initialized data */
bcopy(init, mod_info.segInfo.dataAddr, mod_info.segInfo.dataSize);
}
/* Jump to PROGRAM main() */
PROGRAM_main(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10);
}
--
Georg Feil
| http://www.sgl.crestech.ca/
Space Geodynamics Laboratory | Email: ge...@sgl.crestech.ca
CRESTech | Phone: (416) 665-5458
4850 Keele St./North York/Ont/Canada/M3J 3K1 | Fax: (416) 665-1815
We recently completed the first phase of porting our compiler,
Comeau C++, to the TMS320C82, with the TI C compiler (hosted on Solaris/SPARC)
We set it up traditionally "like UNIX", and based upon your points
below wonder if there is a problem, a culture, or just pragmatics
tht might not matter. See below.
>> 1. Why can't we use main function with C language?
>>
>> When we programmed some applications with main function, We couldn't
>> download those applications. Undefined symbol (__eabi) error occurred.
>
>Lemme guess. PowerPC, right? :)
>
>Including main() causes the compiler/linker to automagically link in a
>bunch of Other Stuff. In Unix, including main() causes prologue code
>(which initializes the C standard library) to run, etc. In C++, this
>prologue code initializes static constructors.
Although Standard C++ does not require main() to be the static ctor
"clue in", we use it as such often on some platforms, since it is allowed.
Even despite the one address space comment above, what's wrong
with treating it that way?
>vxWorks on the powerPC, on the other hand, corresponds to a
>specification
>called EABI (Embedded Application Binary Interface); which calls for a
>function __eabi to be invoked when a program starts. This is, however,
>Not What You Want in vxWorks.
>
>The bottom line: don't call anything main().
In brief, what's wrong with __eabi being called on vxWorks?
>> 2. In tornado shell, we can't execute some programs many times. All
>> Those programs have global variables. So, After executing those
>> programs, Global variables contain some values that are different from
>> program startup values.
>>
>> How do we initialize all global variables on program startup?
>
>Do so explicitly. The static initialization happens only once. For
>those objects linked with the kernel, static initialization happens when
>the system starts. If you use the dynamic loader, the initialization
>happens when the module is loaded. However, "restarting" the program
>does
>not cause globals to be initialized.
So with whatever C++ combo with Tornado you're referring to,
restarting won't redo static initializers?
>Oh, and one more thing. The automatic cleanup that you get in Unix when
>a program dies (all memory blocks freed, stdio flushed, all files
>closed)
>does NOT happen in vxWorks. You **MUST** free all resources you use
>yourself.
We also added in static destruction stuff, why is that a problem
(assuming it's needed)?
>> Why don't vxworks initialize global variables on program startup.
>
>vxWorks views the entire system as a "program"; all the modules are part
>of that program.
This doesn't seems like a good reason, alone that is.
This is to say, this is somewhat akin to saying that shared libs
on UNIX of DLLs on Win shouldn't take care of any initialization,
and/or arrange for them to be done.
>> When Initialization occurs? Object code downloading?
>
>Globals defined in the module are initialized when you download the
>module,
>but at no time after. (Unless you unload the module and load it again;
>this will ause them to be re-initialized).
Data only?
>> 3. On program exit, is dynamically allocated memory automatically freed?
>
>Nope.
>
>> Otherwise, we must free all dynamically allocated memory explicitly?
>
>Yup.
This implies it's either erroneous or unncessary to perform static
destructors. Although we can imagine apps that won't care,
the above sems to imply it's always true???
- Greg
--
Comeau Computing, 91-34 120th Street, Richmond Hill, NY, 11418-3214
Producers of Comeau C/C++ 4.2.38 -- NOTE 4.2.42 BETAS NOW AVAILABLE
Email: com...@comeaucomputing.com / Voice:718-945-0009 / Fax:718-441-2310
*** WEB: http://www.comeaucomputing.com ***
Greg Comeau wrote:
Because the single address space of VxWorks already defines a main( ) andwill not allow
a duplicate. Period.
>
>
> >vxWorks on the powerPC, on the other hand, corresponds to a
> >specification
> >called EABI (Embedded Application Binary Interface); which calls for a
> >function __eabi to be invoked when a program starts. This is, however,
> >Not What You Want in vxWorks.
> >
> >The bottom line: don't call anything main().
>
> In brief, what's wrong with __eabi being called on vxWorks?
Nothing, just the fact that if you're going to write your own main( ), you'regoing to
have to supply your own __eabi.
>
>
> >> 2. In tornado shell, we can't execute some programs many times. All
> >> Those programs have global variables. So, After executing those
> >> programs, Global variables contain some values that are different from
> >> program startup values.
> >>
> >> How do we initialize all global variables on program startup?
> >
> >Do so explicitly. The static initialization happens only once. For
> >those objects linked with the kernel, static initialization happens when
> >the system starts. If you use the dynamic loader, the initialization
> >happens when the module is loaded. However, "restarting" the program
> >does
> >not cause globals to be initialized.
>
> So with whatever C++ combo with Tornado you're referring to,
> restarting won't redo static initializers?
C++ and Tornado notwithstanding, VxWorks initializes your globals at module load time
only.Thus the requirement that you initialize any other time you need it done.
>
>
> >Oh, and one more thing. The automatic cleanup that you get in Unix when
> >a program dies (all memory blocks freed, stdio flushed, all files
> >closed)
> >does NOT happen in vxWorks. You **MUST** free all resources you use
> >yourself.
>
> We also added in static destruction stuff, why is that a problem
> (assuming it's needed)?
>
> >> Why don't vxworks initialize global variables on program startup.
> >
> >vxWorks views the entire system as a "program"; all the modules are part
> >of that program.
>
> This doesn't seems like a good reason, alone that is.
> This is to say, this is somewhat akin to saying that shared libs
> on UNIX of DLLs on Win shouldn't take care of any initialization,
> and/or arrange for them to be done.
>
I am not sure if your objection here is practical or philosophical?The practical answer
is, you must initiliaze your globals in VxWorks
*each time* your program runs.
> >> When Initialization occurs? Object code downloading?
> >
> >Globals defined in the module are initialized when you download the
> >module,
> >but at no time after. (Unless you unload the module and load it again;
> >this will ause them to be re-initialized).
>
> Data only?
data inits and ctors called.
>
>
> >> 3. On program exit, is dynamically allocated memory automatically freed?
> >
> >Nope.
> >
> >> Otherwise, we must free all dynamically allocated memory explicitly?
> >
> >Yup.
>
> This implies it's either erroneous or unncessary to perform static
> destructors. Although we can imagine apps that won't care,
> the above sems to imply it's always true???
If you called malloc() or new, you are *always* responsible for calling free() or
delete, respectively.A statically declared C++ object will die on its own.
Good job.
One modification that might be useful would be to malloc and copy all
the arguments to the main function (treating arg1-arg10 as strings),
for two reasons:
1) If you are porting UNIX code, many unix programs do nasty things
like
modfifying argv[]. In vxWorks, where arguments are not copied into the
child program's "address space" by default; this behavior can cause All
Sorts Of Problems.
2) Even if the child program doesn't modify the arguments; the caller
may be
passing strings to the client that sit on the stack (or are otherwise
non-const)
and may spawn the child as a separate task. Lots of nastiness results,
of course, if a child task goes and scribbles on the parent's stack in a
random fashion....
You're writing a C++ compiler for the C8x? You poor bastard! :)
(For those not familiar, the TSM320C8x is a parallel DSP whose
architecture is, how shall I say it, bizarre....)
I wasn't aware that vxWorks ran on C80s.
> We set it up traditionally "like UNIX", and based upon your points
> below wonder if there is a problem, a culture, or just pragmatics
> tht might not matter. See below.
vxWorks ain't UNIX; the underlying architecture is radically different.
Despite the presense of a POSIX-ish API, programming practices that
are commonplace in Unix-land will get you into trouble in vxWorks.
And this is ignoring the tooling issues you ask about below.
A couple basic rules for working in vxWorks:
1) Avoid globals whenever possible. In Unix this is good advice as
well, but many Unix (older ones especially) are single-threaded so
globals
aren't quite as bad. ANY program that uses globals in vxWorks will take
some work to be re-entrant.
2) Don't define short function names with external linkage (short names
with
static linkage aren't a problem). A vxWorks "program" shares the symbol
table
with all other programs in the system. (This is a big reason why you
shouldn't
use main() below).
3) Clean up after yourself; this system willnot do this for you.
> >> 1. Why can't we use main function with C language?
> >>
> >> When we programmed some applications with main function, We couldn't
> >> download those applications. Undefined symbol (__eabi) error occurred.
> >
> >Lemme guess. PowerPC, right? :)
> >
> >Including main() causes the compiler/linker to automagically link in a
> >bunch of Other Stuff. In Unix, including main() causes prologue code
> >(which initializes the C standard library) to run, etc. In C++, this
> >prologue code initializes static constructors.
>
> Although Standard C++ does not require main() to be the static ctor
> "clue in", we use it as such often on some platforms, since it is allowed.
> Even despite the one address space comment above, what's wrong
> with treating it that way?
Well... in addition to having a single address space, vxWorks also has a
single namespace. If a symbol is declared with external linkage;
vxWorks
doesn't care much for having multiple symbols with the same name. If
you
try to link two modules, both with "int main()" defined, at compile
time--
you'll get a linker error. If you use the loader to load a module that
defines main() and another module already defines main(), the other
module's main() will get squashed. (The loader, BTW, will not warn you
about duplicate symbols squashed in this manner.)
(A question for you: What does the new ISO/ANSI standard say about main
and namespaces--is main() part of namespace std? )
> >vxWorks on the powerPC, on the other hand, corresponds to a
> >specification
> >called EABI (Embedded Application Binary Interface); which calls for a
> >function __eabi to be invoked when a program starts. This is, however,
> >Not What You Want in vxWorks.
> >
> >The bottom line: don't call anything main().
>
> In brief, what's wrong with __eabi being called on vxWorks?
Well, you get to write it for yourself. In the case of the C80, the
__eabi
function may or may not exist; it is a PowerPC thing.
> >> 2. In tornado shell, we can't execute some programs many times. All
> >> Those programs have global variables. So, After executing those
> >> programs, Global variables contain some values that are different from
> >> program startup values.
> >>
> >> How do we initialize all global variables on program startup?
> >
> >Do so explicitly. The static initialization happens only once. For
> >those objects linked with the kernel, static initialization happens when
> >the system starts. If you use the dynamic loader, the initialization
> >happens when the module is loaded. However, "restarting" the program
> >does
> >not cause globals to be initialized.
> So with whatever C++ combo with Tornado you're referring to,
> restarting won't redo static initializers?
No. At least not automagically.
The default behavior of vxWorks is as follows:
1) Static constructors of modules statically linked to the kernel are
run somewhere in
the BSP init; after all drivers, etc are brought up but before usrRoot()
starts the shell
and/or the user application.
2) Static constructors of modules dynamically loaded into a running
system are run at load
time.
3) Static destructors of modules dynamically loaded into a running
system are run when
you UNLOAD the module. (I think; as a rule I tend to avoid static
destructors like the
plague.) This assumes that you haven't loaded ANOTHER module...see
below.
4) Static destructors of modules statically linked to the kernel are,
as far as I know,
never run.
You can disable 2) and 3) (on a SYSTEM-wide basis, not per module) if
you want, in which
case you can specify when to run static constructors and/or destrctors.
This scheme has a LOT of problems. The functions that get defined for
you
(by a tool called the "muncher", which does a similar thing to "collect"
in many Unix
environemnts; except that you have to arrange for it to be called
explicitly in your
build environment rather than having the compiler driver do it for you)
are given a
well-known name, and entered into the global symbol table (with external
linkage).
Something like RunStaticCtors() and RunStaticDtors() (I cannot remember
offhand, and
I am at home, without the relevant manual handy).
If you load one module, and then another, the RunStaticC/Dtors()
functions of the NEW module
(if present; modules consisting only of C code won't have these
functions) will replace
the old ones in the symbol table. The automatic technique might still
work (if WRS
were smart, they'd resolve both symbols into function pointers at load
time, rather than
resolving the symbol at unload time); but the manual technique might
cause problems if
you try and run destructors from the shell.
> >Oh, and one more thing. The automatic cleanup that you get in Unix when
> >a program dies (all memory blocks freed, stdio flushed, all files
> >closed)
> >does NOT happen in vxWorks. You **MUST** free all resources you use
> >yourself.
>
> We also added in static destruction stuff, why is that a problem
> (assuming it's needed)?
See above. vxWorks probably won't ever call your static destructors
unless you tell it to.
> >> Why don't vxworks initialize global variables on program startup.
> >
> >vxWorks views the entire system as a "program"; all the modules are part
> >of that program.
>
> This doesn't seems like a good reason, alone that is.
> This is to say, this is somewhat akin to saying that shared libs
> on UNIX of DLLs on Win shouldn't take care of any initialization,
> and/or arrange for them to be done.
However, Win32 DLLs and Unix shared libraries have a separate copy of
.data
and .bss for each process that attaches to 'em. If I have a .so file
that declares a global to be one at initialization--each program that
links
to the module can assume that this will be the case.
vxWorks modules are more like--and this is a scary thought--Windows 3.x
DLLs.
In other words, the address space of the DLL is system wide.
> >> When Initialization occurs? Object code downloading?
> >
> >Globals defined in the module are initialized when you download the
> >module,
> >but at no time after. (Unless you unload the module and load it again;
> >this will ause them to be re-initialized).
> Data only?
Data and BSS. VxWorks does zero out the BSS for you. (vxWorks modules
frequently also contain COMMON symbols, which the loader tries to treat
as BSS, though it allocates a separate memory block for each common
symbol.
Occasionally, at least on powerPC, it computes the size wrong and
gleefully
trashes the heap.)
> >> 3. On program exit, is dynamically allocated memory automatically freed?
> >
> >Nope.
> >
> >> Otherwise, we must free all dynamically allocated memory explicitly?
> >
> >Yup.
> This implies it's either erroneous or unncessary to perform static
> destructors. Although we can imagine apps that won't care,
> the above sems to imply it's always true???
Erroneous; vxWorks won't call them reliably.
The BEST you can hope for is to run each module as a separate task, add
a "task delete hook" to call the destructors, and pray. :) You still
won't have re-entrant code, and if the task dies an unnatural death
static destructors might still run in the wrong context, or not at all.
The best thing to do, like I said above, is avoid global variables
(including
global objects) entirely. I tend to define exactly ONE (or at most two)
per module, which I can make a "task variable" if need be to achieve
re-entrancy.
Scott
> - Greg
> --
> Comeau Computing, 91-34 120th Street, Richmond Hill, NY, 11418-3214
> Producers of Comeau C/C++ 4.2.38 -- NOTE 4.2.42 BETAS NOW AVAILABLE
> Email: com...@comeaucomputing.com / Voice:718-945-0009 / Fax:718-441-2310
> *** WEB: http://www.comeaucomputing.com ***
--
What VxWorks does when you use ld() or moduleLoad() is done implicitly by
operating systems like Unix. Allocating memory, loading sections into memory,
processing relocatable entries, etc., are all handled by Unix without your
knowledge.
If Unix required you to perform load actions explicitly, you would have the same
issues that exist in VxWorks to deal with. Global variable initial values are
defined at load time. Static constructors are (optionally) executed at load
time. If you want these actions to be carried out again, you must reload the
executable. Reloading the executable is EXACTLY what you are doing every time
you run a program under Unix.
Having separate load and execution steps allows for greater flexibility, but, as
evidenced by this thread, also causes greater confusion. To ensure that your
programs execute the same way each time they are run, reload them each time they
are run. If you choose not to do that, accept the responsibility of creating
your own solution.
Charlie Grames
The Boeing Company
Charles.R.Grames @ boeing.com
Ok, thanks. We completed the initial port of Comeau C++ a few months ago,
so some of these Q's are just for confirmation.
>> >vxWorks on the powerPC, on the other hand, corresponds to a
>> >specification
>> >called EABI (Embedded Application Binary Interface); which calls for a
>> >function __eabi to be invoked when a program starts. This is, however,
>> >Not What You Want in vxWorks.
>> >
>> >The bottom line: don't call anything main().
>>
>> In brief, what's wrong with __eabi being called on vxWorks?
>
>Nothing, just the fact that if you're going to write your own main(),
>you're going to have to supply your own __eabi.
Given the above, this seems to follow.
>> >> 2. In tornado shell, we can't execute some programs many times. All
>> >> Those programs have global variables. So, After executing those
>> >> programs, Global variables contain some values that are different from
>> >> program startup values.
>> >>
>> >> How do we initialize all global variables on program startup?
>> >
>> >Do so explicitly. The static initialization happens only once. For
>> >those objects linked with the kernel, static initialization happens when
>> >the system starts. If you use the dynamic loader, the initialization
>> >happens when the module is loaded. However, "restarting" the program
>> >does
>> >not cause globals to be initialized.
>>
>> So with whatever C++ combo with Tornado you're referring to,
>> restarting won't redo static initializers?
>
>C++ and Tornado notwithstanding, VxWorks initializes your globals at
>module load time only.Thus the requirement that you initialize any other
>time you need it done.
One scheme we use is to initialize (non-constant initializers as
well as static ctors init phase that is) from main(). Since it was
clear that main() could not be used directly for practical purposes,
we simply provided for that you can tell the compiler what an
alternative name for main() is.
>> >Oh, and one more thing. The automatic cleanup that you get in Unix when
>> >a program dies (all memory blocks freed, stdio flushed, all files
>> >closed)
>> >does NOT happen in vxWorks. You **MUST** free all resources you use
>> >yourself.
>>
>> We also added in static destruction stuff, why is that a problem
>> (assuming it's needed)?
>>
>> >> Why don't vxworks initialize global variables on program startup.
>> >
>> >vxWorks views the entire system as a "program"; all the modules are part
>> >of that program.
>>
>> This doesn't seems like a good reason, alone that is.
>> This is to say, this is somewhat akin to saying that shared libs
>> on UNIX of DLLs on Win shouldn't take care of any initialization,
>> and/or arrange for them to be done.
>
>I am not sure if your objection here is practical or philosophical?
>he practical answer is, you must initiliaze your globals in VxWorks
>*each time* your program runs.
It was a bit of both. Clearly if that's the way it is then that's
the way it is, sure. I both wanted to confim this and theorize a bit too :)
>> >> When Initialization occurs? Object code downloading?
>> >
>> >Globals defined in the module are initialized when you download the
>> >module,
>> >but at no time after. (Unless you unload the module and load it again;
>> >this will ause them to be re-initialized).
>>
>> Data only?
>
>data inits and ctors called.
>
>>
>>
>> >> 3. On program exit, is dynamically allocated memory automatically freed?
>> >
>> >Nope.
>> >
>> >> Otherwise, we must free all dynamically allocated memory explicitly?
>> >
>> >Yup.
>>
>> This implies it's either erroneous or unncessary to perform static
>> destructors. Although we can imagine apps that won't care,
>> the above sems to imply it's always true???
>
>If you called malloc() or new, you are *always* responsible for calling free() or
>delete, respectively.A statically declared C++ object will die on its own.
In the same way as the ctors are called as you say above?
That is, do they just die, or do their dtors get run too?
Again, still just curious because although the customer did not care
about static destructors, we can arrange for them to be called through
our own termination code, and it seemed fine, but we were not completely
sure if we were completing/violating with something else (we don't think
so since we use out own naming and setup, but it's still worth double
checking for future situations).
Ooo, er, thanks :) Actually, we did the initial port a few months
back. We did some work inhouse since then too.
>(For those not familiar, the TSM320C8x is a parallel DSP whose
> architecture is, how shall I say it, bizarre....)
>
>I wasn't aware that vxWorks ran on C80s.
Well, we're glad it's hosted on Solaris :)
>> We set it up traditionally "like UNIX", and based upon your points
>> below wonder if there is a problem, a culture, or just pragmatics
>> tht might not matter. See below.
>
>vxWorks ain't UNIX; the underlying architecture is radically different.
>Despite the presense of a POSIX-ish API, programming practices that
>are commonplace in Unix-land will get you into trouble in vxWorks.
>And this is ignoring the tooling issues you ask about below.
Possible trouble areas is actually what I'm interesting in double checking.
>A couple basic rules for working in vxWorks:
>
>1) Avoid globals whenever possible. In Unix this is good advice as
>well, but many Unix (older ones especially) are single-threaded so
>globals
>aren't quite as bad. ANY program that uses globals in vxWorks will take
>some work to be re-entrant.
Or alternatively, just be reloaded?
>2) Don't define short function names with external linkage (short names
>with static linkage aren't a problem). A vxWorks "program" shares the
>symbol table with all other programs in the system. (This is a big
>reason why you shouldn't use main() below).
Are you concerned about global name space pollution here and
the likelyhood of picking a name the vxWorks already has?
>3) Clean up after yourself; this system willnot do this for you.
Yes, we've done that.
>> >> 1. Why can't we use main function with C language?
>> >>
>> >> When we programmed some applications with main function, We couldn't
>> >> download those applications. Undefined symbol (__eabi) error occurred.
>> >
>> >Lemme guess. PowerPC, right? :)
>> >
>> >Including main() causes the compiler/linker to automagically link in a
>> >bunch of Other Stuff. In Unix, including main() causes prologue code
>> >(which initializes the C standard library) to run, etc. In C++, this
>> >prologue code initializes static constructors.
>>
>> Although Standard C++ does not require main() to be the static ctor
>> "clue in", we use it as such often on some platforms, since it is allowed.
>> Even despite the one address space comment above, what's wrong
>> with treating it that way?
>
>Well... in addition to having a single address space, vxWorks also has a
>single namespace. If a symbol is declared with external linkage;
>vxWorks doesn't care much for having multiple symbols with the same name.
>If you try to link two modules, both with "int main()" defined,
>at compile time-- you'll get a linker error.
Right "as usual".
>If you use the loader to load a module that
>defines main() and another module already defines main(), the other
>module's main() will get squashed. (The loader, BTW, will not warn you
>about duplicate symbols squashed in this manner.)
Ok, gotcha. Ok, we did provide an option to rename your main
(at the source code level). Sounds like the right thing.
>(A question for you: What does the new ISO/ANSI standard say about main
>and namespaces--is main() part of namespace std? )
main is special, but not part of std. Given what you said about though,
it wouldn't seem to matter much, because even if if were, more than one
std::main would squashed the former one, no?
> > >vxWorks on the powerPC, on the other hand, corresponds to a
>> >specification
>> >called EABI (Embedded Application Binary Interface); which calls for a
>> >function __eabi to be invoked when a program starts. This is, however,
>> >Not What You Want in vxWorks.
>> >
>> >The bottom line: don't call anything main().
>>
>> In brief, what's wrong with __eabi being called on vxWorks?
>
>Well, you get to write it for yourself. In the case of the C80, the
>__eabi function may or may not exist; it is a PowerPC thing.
Yes, this is strating to rings some bells from having read the
docs earlier this year (I just didn't recall it being called that...)
>> >> 2. In tornado shell, we can't execute some programs many times. All
>> >> Those programs have global variables. So, After executing those
>> >> programs, Global variables contain some values that are different from
>> >> program startup values.
>> >>
>> >> How do we initialize all global variables on program startup?
>> >
>> >Do so explicitly. The static initialization happens only once. For
>> >those objects linked with the kernel, static initialization happens when
>> >the system starts. If you use the dynamic loader, the initialization
>> >happens when the module is loaded. However, "restarting" the program
>> >does
>> >not cause globals to be initialized.
>
>> So with whatever C++ combo with Tornado you're referring to,
>> restarting won't redo static initializers?
>
>No. At least not automagically.
>
>The default behavior of vxWorks is as follows:
>
>1) Static constructors of modules statically linked to the kernel are
>run somewhere in the BSP init; after all drivers, etc are brought up
>but before usrRoot() starts the shell and/or the user application.
Make sense.
>2) Static constructors of modules dynamically loaded into a running
>system are run at load time.
Can it also be done at runtime?
>3) Static destructors of modules dynamically loaded into a running
>system are run when you UNLOAD the module. (I think; as a rule
>I tend to avoid static destructors like the plague.) This assumes
>that you haven't loaded ANOTHER module...see below.
We have special code which calls the ctors when the program starts,
and the last this the special code does is establish special code
which gets run when the program terminates. This is all independent
of the vxWorks scheme, so it shouldn't bump heads with it (at least
technically that is).
>4) Static destructors of modules statically linked to the kernel are,
>as far as I know, never run.
Ok.
>
>You can disable 2) and 3) (on a SYSTEM-wide basis, not per module) if
>you want, in which case you can specify when to run static constructors
>and/or destrctors.
Ok, 2/3 did seem too rigid. What are the alternative time to run
that it gives you? Not at all? At program start? At module start?
>This scheme has a LOT of problems. The functions that get defined for
>you (by a tool called the "muncher", which does a similar thing to
>"collect" in many Unix environemnts; except that you have to arrange
>for it to be called explicitly in your build environment rather than
>having the compiler driver do it for you) are given a
>well-known name, and entered into the global symbol table (with
>external linkage). Something like RunStaticCtors() and
>RunStaticDtors() (I cannot remember offhand, and
>I am at home, without the relevant manual handy).
We use many schemes depending upon the platform. For the C82
we used a scheme similar to above but the compiler driver completes
the scheme so that it will be done automatically.
>If you load one module, and then another, the RunStaticC/Dtors()
>functions of the NEW module (if present; modules consisting only
>of C code won't have these functions) will replace the old ones
>in the symbol table. The automatic technique might still
>work (if WRS were smart, they'd resolve both symbols into function
>pointers at load time, rather than resolving the symbol at unload time);
>but the manual technique might cause problems if you try and run
>destructors from the shell.
Aha!, good info, thanks!
>> >Oh, and one more thing. The automatic cleanup that you get in Unix
>> >when a program dies (all memory blocks freed, stdio flushed, all files
>> >closed) does NOT happen in vxWorks. You **MUST** free all resources
>> >you use yourself.
>>
>> We also added in static destruction stuff, why is that a problem
>> (assuming it's needed)?
>
>See above. vxWorks probably won't ever call your static destructors
>unless you tell it to.
We do (though the customer did not have any static dtors).
>> >> Why don't vxworks initialize global variables on program startup.
>> >
>> >vxWorks views the entire system as a "program"; all the modules are part
>> >of that program.
>>
>> This doesn't seems like a good reason, alone that is.
>> This is to say, this is somewhat akin to saying that shared libs
>> on UNIX of DLLs on Win shouldn't take care of any initialization,
>> and/or arrange for them to be done.
>
>However, Win32 DLLs and Unix shared libraries have a separate copy of
>.data and .bss for each process that attaches to 'em. If I have
>a .so file that declares a global to be one at initialization--
>each program that links to the module can assume that this will be
>the case.
>
>vxWorks modules are more like--and this is a scary thought--Windows 3.x
>DLLs. In other words, the address space of the DLL is system wide.
Ok, understood.
>> >> When Initialization occurs? Object code downloading?
>> >
>> >Globals defined in the module are initialized when you download the
>> >module,
>> >but at no time after. (Unless you unload the module and load it again;
>> >this will ause them to be re-initialized).
>
>> Data only?
>
>Data and BSS. VxWorks does zero out the BSS for you. (vxWorks modules
>frequently also contain COMMON symbols, which the loader tries to treat
>as BSS, though it allocates a separate memory block for each common
>symbol. Occasionally, at least on powerPC, it computes the size wrong and
>gleefully trashes the heap.)
That sounds good enough for us, but something we'll keep an eye out for.
>> >> 3. On program exit, is dynamically allocated memory automatically freed?
>> >
>> >Nope.
>> >
>> >> Otherwise, we must free all dynamically allocated memory explicitly?
>> >
>> >Yup.
>
>> This implies it's either erroneous or unncessary to perform static
>> destructors. Although we can imagine apps that won't care,
>> the above sems to imply it's always true???
>
>Erroneous; vxWorks won't call them reliably.
>
>The BEST you can hope for is to run each module as a separate task, add
>a "task delete hook" to call the destructors, and pray. :) You still
>won't have re-entrant code, and if the task dies an unnatural death
>static destructors might still run in the wrong context, or not at all.
When run as a seperate task, does the name squashing issues
from above go away?
This thread is getting pretty involved. It's getting difficult to separate the
questions from the answers.
As far as static constructors and destructors are concerned, you can control
whether they are executed automatically at program load and unload with the
routine cplusXtorSet() (see the reference manual). The default strategy is
automatic, but you can change it to mnaual. You can then run cplusCtors() to
run your static constructors and cplusDtors() to run your static destructors
(again, see the reference manual). cplusCtors() and cplusDtors() accept a
module name (in which case, they act only on the static con/destructors for that
module), or the module name can be omitted/null (in which case, they act on all
loaded modules--even if those modules have already had static con/destructors
executed!).
Charlie Grames
The Boeing Company
Charles.R.Grames @ boeing.com
Greg Comeau wrote:
<big snip>
> >2) Static constructors of modules dynamically loaded into a running
> >system are run at load time.
>
> Can it also be done at runtime?
>
> >3) Static destructors of modules dynamically loaded into a running
> >system are run when you UNLOAD the module. (I think; as a rule
> >I tend to avoid static destructors like the plague.) This assumes
> >that you haven't loaded ANOTHER module...see below.
>
> We have special code which calls the ctors when the program starts,
> and the last this the special code does is establish special code
> which gets run when the program terminates. This is all independent
> of the vxWorks scheme, so it shouldn't bump heads with it (at least
> technically that is).
<another big snip>
That will get you proper initialization a second time; it WON'T
get you re-entrancy. If you start up two instances of your module at
the
same time, they will gleefully stomp on each other.
> >2) Don't define short function names with external linkage (short names
> >with static linkage aren't a problem). A vxWorks "program" shares the
> >symbol table with all other programs in the system. (This is a big
> >reason why you shouldn't use main() below).
> Are you concerned about global name space pollution here and
> the likelyhood of picking a name the vxWorks already has?
It's not hard to do...vxWorks defines some awfully short symbol
names. There are lots of functions in usrLib() like l() or d()
or m()..... This is intentional; these are debugging facilities
that are meant to be invoked from the shell; and WRS apparently
knows what lazy typists engineers are. :)
Yup.
> >(A question for you: What does the new ISO/ANSI standard say about main
> >and namespaces--is main() part of namespace std? )
>
> main is special, but not part of std. Given what you said about though,
> it wouldn't seem to matter much, because even if if were, more than one
> std::main would squashed the former one, no?
It would... if you could have foo::main and bar::main, however, THOSE
wouldn't
squash each other.
As long as you don't "munch", and create the symbols vxWorks is working
for,
it should work.
> >4) Static destructors of modules statically linked to the kernel are,
> >as far as I know, never run.
>
> Ok.
>
> >
> >You can disable 2) and 3) (on a SYSTEM-wide basis, not per module) if
> >you want, in which case you can specify when to run static constructors
> >and/or destrctors.
>
> Ok, 2/3 did seem too rigid. What are the alternative time to run
> that it gives you? Not at all? At program start? At module start?
Whenever you want; you have to invoke the functions manually. If you
don't
disable 2) and 3), construction happens when you type ld() or reld();
destruction when you type reld() or unld(). (Or the equivalent
functions
to these, like loadModule() or unldModuleById(), etc.)
BTW... you either disable BOTH of 2) and 3), or neither; you cannot
disable
one of them but not the other.
> >This scheme has a LOT of problems. The functions that get defined for
> >you (by a tool called the "muncher", which does a similar thing to
> >"collect" in many Unix environemnts; except that you have to arrange
> >for it to be called explicitly in your build environment rather than
> >having the compiler driver do it for you) are given a
> >well-known name, and entered into the global symbol table (with
> >external linkage). Something like RunStaticCtors() and
> >RunStaticDtors() (I cannot remember offhand, and
> >I am at home, without the relevant manual handy).
>
> We use many schemes depending upon the platform. For the C82
> we used a scheme similar to above but the compiler driver completes
> the scheme so that it will be done automatically.
Usually, compiler drivers that do this link into main() (or __main()
on some systems). Can you specify an alternate entry point to hook
into?
WRS seems to not know how to round to powers of two appropriately... :)
> >> >> 3. On program exit, is dynamically allocated memory automatically freed?
> >> >
> >> >Nope.
> >> >
> >> >> Otherwise, we must free all dynamically allocated memory explicitly?
> >> >
> >> >Yup.
> >
> >> This implies it's either erroneous or unncessary to perform static
> >> destructors. Although we can imagine apps that won't care,
> >> the above sems to imply it's always true???
> >
> >Erroneous; vxWorks won't call them reliably.
> >
> >The BEST you can hope for is to run each module as a separate task, add
> >a "task delete hook" to call the destructors, and pray. :) You still
> >won't have re-entrant code, and if the task dies an unnatural death
> >static destructors might still run in the wrong context, or not at all.
>
> When run as a seperate task, does the name squashing issues
> from above go away?
No, the symbol table is global.
Of course, "name squashing" is only a problem when linking modules
together
using the dynamic loader; or running functions from the shell; these
involve
lookups in the symbol table. Internal function calls are resolved by
the
linker (just like normal), and don't give a rip about what is in the
symbol
table.
> - Greg
> --
> Comeau Computing, 91-34 120th Street, Richmond Hill, NY, 11418-3214
> Producers of Comeau C/C++ 4.2.38 -- NOTE 4.2.42 BETAS NOW AVAILABLE
> Email: com...@comeaucomputing.com / Voice:718-945-0009 / Fax:718-441-2310
> *** WEB: http://www.comeaucomputing.com ***
--
I am a first man to start this thread.
When I received engineer_scotty's answer, I think my question is addressed.
But, Where is that information, engineer_scotty's answer ?
Tornado's user manual? Vxworks programmer's guide?
What document contain that information?
Thanks.
GoodBye.