[lwip-users] Initialization of global variables

71 views
Skip to first unread message

Piotr Piwko

unread,
Nov 5, 2010, 2:36:12 PM11/5/10
to lwip-...@nongnu.org
Hello,

I currently implement the LwIP stack under u-boot environment and I
have one notice regarding global variables initialization. I think
that every global variable which are not static should be initialized
by NULL or 0 value. I mean for example:

file tcp.c:
struct tcp_pcb *tcp_bound_pcbs;
union tcp_listen_pcbs_t tcp_listen_pcbs;
struct tcp_pcb *tcp_active_pcbs;
struct tcp_pcb *tcp_tw_pcbs;

file udp.c:
struct udp_pcb *udp_pcbs;

file netif.c:
struct netif *netif_list;
struct netif *netif_default;

If I leave they uninitialized, after compilation and link operation
they will contain random values which causes the system crash during
LwIP initialized functions. Assumption that they will be automatically
filled by 0 is wrong and non-portable.

This modification can really save a lot of time during integration :)

Anyway I am impressed with LwIP project. It is very useful part of
software. Good job guys!

Regards,

--
Piotr Piwko
http://www.embedded-engineering.pl/

_______________________________________________
lwip-users mailing list
lwip-...@nongnu.org
http://lists.nongnu.org/mailman/listinfo/lwip-users

Rick Solotke

unread,
Nov 5, 2010, 2:42:19 PM11/5/10
to Mailing list for lwIP users
Hi all,

I just wanted to pop in and say that I have observed and debugged the
same problem, specifically for the UDP and TCP PCB lists. It would be
great if the code could be changed to explicitly initialize these to
NULL.

Cheers,
Rick

Simon Goldschmidt

unread,
Nov 5, 2010, 2:53:25 PM11/5/10
to Mailing list for lwIP users
Hey Piotr,

I hate to turn you down on that, but the variables are deliberately not being initialized: when not initialized (and thus implicitly zeroed at startup), they are put into the uninitialized section and no space on disk/in flash is needed. However when they are initialized to NULL, they are put NGO the initialized data section, which is present on disk/in flash, too.

As to the portability: the C standard requires non initialized data to be initialized to zero at startup. It is a common error in self-made ports to leave out the zeroing of the uninitialized data section (.bss for gnu bcc).

Simon

mat henshall

unread,
Nov 5, 2010, 3:07:12 PM11/5/10
to Mailing list for lwIP users
Simon,

I have hit this problem where an environment by default turns off the
initialization of globals for 'efficiency' and expects an application
to explicit zero out the globals and statics as needed. For example, I
use an ultra low powered wifi chip that has lwIP in ROM and it loads
applicaiton code from flash on 'wake up'. TIme is energy, so the less
time the chip takes to wake up and see if it really needs to do
something and the if not, fall asleep again, the better. Only if you
really want to do something might you want to then initialize the
various modules etc.

When using subsystems and third party libraries, it is always a
little error prone and painful to collect all the various globals into
a 'init_to_zero' function. It would be more pleasant and robust to
have the optional function provided by the library.

Mat

--

Mat Henshall
Founder and CEO, Square Connect, Inc.
San Jose, CA
www.squareconnect.com
cell: 650.814.7585

Simon Goldschmidt

unread,
Nov 5, 2010, 3:44:09 PM11/5/10
to Mailing list for lwIP users
Excerpt from the ANSI-C Standard (e.g. http://flash-gordon.me.uk/ansi.c.txt):
 If an object that has static storage duration is not initialized
explicitly, it is initialized implicitly as if every member that has
arithmetic type were assigned 0 and every member that has pointer type
were assigned a null pointer constant.  If an object that has
automatic storage duration is not initialized explicitly, its value is
indeterminate./65/
As you can see, there's absolutely no portability issue here! Also, there's no performance gain in not zeroing the variables at startup: when they are explicitly initialized by the application, the loader has to load their initial values from flash/ROM to RAM. When relying on zeroing by the loader, you only have to write zeros starting from a defined point, for a defined length. What's faster now, reading AND writing or only writing?

Also, if you write an ANSI-C compatible loader/startup code, there's no need to manually collect global variables and initialize them with your own C code. also, static globals can't be collected that way as you can't access them from another file.

Finally, we've been having his discussion over and over again, and the ANSI C standard didn't change over the years in that regard. I'm still open for really pressing issues regarding portability, but up to now, I (and other lwIP developers, I guess) haven't been convinced this is such an issue. 

Simon
 

 mat henshall <m...@squareconnect.com> wrote:

gold...@gmx.de

unread,
Nov 5, 2010, 4:29:48 PM11/5/10
to Mailing list for lwIP users
Rick Solotke wrote:
> I just wanted to pop in and say that I have observed and debugged the
> same problem, specifically for the UDP and TCP PCB lists. It would be
> great if the code could be changed to explicitly initialize these to
> NULL.
You could have had that problem with any other third-party library. Why
not rely on a fact that is defined in the C standard? It makes the
binary smaller. OK, there might be code where those global variables get
initalized to zero/NULL again (lwIP did that, too, up to 1.2.0, I
think), but it's really smaller (and standard conformant) the way it is now.

If startup time really does matter, it would of course be best to
explicitly put those global variables into a different (non-zeroed)
section where you know they don't need initialization. It's more
portable that way than relying on all the code to not need the
zero-initialization.

Simon

mat henshall

unread,
Nov 5, 2010, 4:51:38 PM11/5/10
to Mailing list for lwIP users
Simon...

It sounds like you are frustrated that this issue has been raised
multiple times and doesn't seem to go away! I am sorry to add to the
'fire'. In all the important things that could be done/worked on this
is, I am sure a low priority.

I wanted to bring to your attention a use case where it makes sense to
turn off compliance with the standard (I believe most compliers allow
this) ... and I pass on the reasoning from the engineers who made the
choice... The circumstance they are concerned about is when a very low
power device wakes up and decides to do nothing.... then not reading,
not writing not zeroing... dong as little as possible can make a big
differnece to battery life. Ofcourse, if you need to wake up and get
on the netowork, all bets are off, and the time taken to zero out is
irrrelevant. But as the ratio of wake up and do nothing to wake up and
talk to the radio is often 100000 to 1 or more, it kind of makes
sense. I believe they measured it.

I have had this discussion with other library writers... and you are
correct, Ansi C says it should be zero'd... doesn't stop me from
having to search through the libraries every time there is a version
increment to see if I need to manually init to zero in these
applications.

A single function where all the global variables are gathered together
and zero'd out that can optionally be linked in makes a cleaner
interface for this odd, but not unknown usecase.

Regards,

mat

mat henshall

unread,
Nov 5, 2010, 5:04:04 PM11/5/10
to Mailing list for lwIP users
Jeff, that is a good solution. Next time I need to do this, I will
look into that.

Thanks.

M
On Fri, Nov 5, 2010 at 2:00 PM, Jeff Barber <jeff...@gmail.com> wrote:
> Why don't you just imitate what the boot loader would do?  Find the
> symbol that indicates the beginning of BSS and the symbol that
> indicates the end, find the difference and clear.  Then only do that
> when your wakeup has decided there's something to do. Linker-dependent
> but usually these symbols are accessible or can be made so.
>
> Jeff

Piotr Piwko

unread,
Nov 5, 2010, 5:26:35 PM11/5/10
to Mailing list for lwIP users
2010/11/5 gold...@gmx.de <gold...@gmx.de>:

> You could have had that problem with any other third-party library. Why not
> rely on a fact that is defined in the C standard? It makes the binary
> smaller. OK, there might be code where those global variables get initalized
> to zero/NULL again (lwIP did that, too, up to 1.2.0, I think), but it's
> really smaller (and standard conformant) the way it is now.

All right, so maybe it should be done in the relevant initialization
routines, tcp_init(), udp_init() and so on?

On the other hand this issue just can be described somewhere in source
code or better in wiki documentation, because it really may take a lot
of time.

Regards,

_______________________________________________

Simon Goldschmidt

unread,
Nov 6, 2010, 7:05:56 AM11/6/10
to Mailing list for lwIP users

Piotr Piwko <piotr...@embedded-engineering.pl> wrote:

> All right, so maybe it should be done in the relevant initialization
> routines, tcp_init(), udp_init() and so on?

That increases code size unnecessarily, too. The only way to not increase code- or ROM-size would be to add an initialization function in every module and let the linker leave that away when not used. However, this cannot be checked easily, as in normal environments (e.g. when testing), you wouldn't notice missing variables in those functions as they are initialized to zero, anyway.

> On the other hand this issue just can be described somewhere in source
> code or better in wiki documentation, because it really may take a lot
> of time.

As many people don't seem to know that ANSI C requires uninitialized globals to be zeroed, it might really be necessary to add that to the description of creating an lwIP port.

Simon

Piotr Piwko

unread,
Nov 6, 2010, 10:54:00 AM11/6/10
to Mailing list for lwIP users
2010/11/6 Simon Goldschmidt <gold...@gmx.de>:

>> All right, so maybe it should be done in the relevant initialization
>> routines, tcp_init(), udp_init() and so on?
>
> That increases code size unnecessarily, too.

Are these few bytes really important? I'm not the LwIP developer and I
don't know every principles and assumptions of project, but I believe
that it will be very useful. You can always add a new definition like
LWIP_GLOBAL_INITIALIZE in lwipopts.h file and according its value you
can initialize the global variables in the relevant module
initialization functions.

_______________________________________________

Bill Auerbach

unread,
Nov 8, 2010, 3:42:20 PM11/8/10
to Mailing list for lwIP users
>On the other hand this issue just can be described somewhere in source
>code or better in wiki documentation, because it really may take a lot
>of time.

It would only take a memset of the right linker generated symbols to zero
BSS before calling lwip_init.

Perhaps the tool vendor of your tools should be asked how to this
initialization since they are breaking the rules, not the lwip developers?

Bill

Reply all
Reply to author
Forward
0 new messages