Discussion:
[Sdcc-user] want to know more about reentrant
cheng chung yan
2001-02-14 09:24:46 UTC
Permalink
dear Dai Yuwen
thanks your response.
as the question of "reentrant", i study the sdcc document, but i can't get the understanding. Could you please tell me more?
thanks
yan

_____________________________________________________
Sent by Hong Kong E-Mail at http://www.hkem.com
It's free. It's easy. Sign up your account Now!
Joris van der Sande
2001-02-14 10:23:26 UTC
Permalink
Post by cheng chung yan
as the question of "reentrant", i study the sdcc document, but i
can't get the understanding. Could you please tell me more?
Reentrant means, as the name suggests, that a function can be re-entered
before the previous function call has ended. This can be either when the
function calls itself, or when you use a multitasking operating system
where multiple tasks invoke the same function.

Due to the limited stack-space, most 8051 compilers apply special tricks to
minimise the amount of stack space used. What they do is store local
variables of the function at a fixed memory location. For example:

void foo(void)
{ int i ;

...
}

Then the local variable `i' will be stored at a fixed location, normally in
the `data' area. If foo() is invoked a second time before the first call
has finished, the new copy of `i' will overwrite the previous value.

If you define the function as `reentrant', the compiler will store the
local variable `i' on the actual hardware stack, or on a "simulated"
software stack in the `xdata' area. Now, if foo() is invoked a second time
before the first call has finished, the new copy of `i' will be pushed on
the stack also, and will therefore not overwrite the previous `i'. If the
second call has finished, the stack is lowered one position and the first
call will continue, using the previous `i'.

Hopefully this has made things a little bit clearer.

Regards,
Joris
Ioan Petrescu
2001-02-14 12:41:10 UTC
Permalink
Post by cheng chung yan
dear Dai Yuwen
thanks your response.
as the question of "reentrant", i study the sdcc document, but i can't
get the understanding. Could you please tell me more?
Post by cheng chung yan
thanks
yan
Hi,
I have seen your problems about reentrant subroutines - for a good
explanation of what they are and how to write them you can read the following:
http://ece.utexas.edu/~valvano/EE360P/PDF/ch5.pdf
it is for 68hc11(!),but the theory applies also to 8051.
Hoping this will help you.
Ioan Petrescu
Rod Boyce
2001-02-14 19:02:04 UTC
Permalink
A brief definition of re-entrant that works for me is:

The function can be called from two different places in the
application (say interrupt and main-line code or two threads) at exactly the
same time without interaction or any adverse effects to either calling
function for example the returned result is what the programmed expected in
each case.

There are possible better definitions I think the K&R ANSIC C book has a
very good definition. Hope this helps in my opinion this is a very
important thing to get right as re-entrant function can be a beautiful tool
to the programmer if used correctly. But note well it can be a nightmare or
any street if it is got wrong as often you cannot say where it all started
to go wrong.


Examples for re-entrant code

int FnDivide( int param1, int param2 )
{
return( param1 / param2 );
}

This example is very simple and may not work on the 8051 but because the
stack is used to pass the parameters and return the result this function
although simple is an example of a re-entrant function. Re-entrancy means
you should have an understanding of the output produced from the compiler
(this is mandatory I would say for any embedded software engineer).


Hope this helps I would strongly suggest that anybody using C to write
programs embedded or otherwise gets a copy of the K&R ANSIC C book this is
the best description of the standard I have seen.

Regards,
Rod Boyce.



-----Original Message-----
From: cheng chung yan [mailto:***@hkem.com]
Sent: Wednesday, 14 February 2001 22:25
To: sdcc-***@lists.sourceforge.net
Cc: ***@microtek.com.cn
Subject: [Sdcc-user] want to know more about
reentrant

dear Dai Yuwen
thanks your response.
as the question of "reentrant", i study the sdcc document,
but i can't get the understanding. Could you please tell me more?
thanks
yan

_____________________________________________________
Sent by Hong Kong E-Mail at http://www.hkem.com
It's free. It's easy. Sign up your account Now!


_______________________________________________
Sdcc-user mailing list
Sdcc-***@lists.sourceforge.net
http://lists.sourceforge.net/lists/listinfo/sdcc-user
Joris van der Sande
2001-02-14 22:30:55 UTC
Permalink
Hi Rod,
Post by Rod Boyce
int FnDivide( int param1, int param2 )
{
return( param1 / param2 );
}
This example is very simple and may not work on the 8051 but
because the stack is used to pass the parameters and return the
result this function although simple is an example of a re-
entrant function.
Sorry, I disagree to this part of your explanation. SDCC will
normally use registers to pass the `param1' and `param2'
variables and the return value in this case, _not_ the stack!
Only because your example function doesn't use local variables,
will it be reentrancy-safe. However, this is not a very robust
example as people might think that any normal function is
reentrant.

Only if you use the `reentrant' keyword, the function will be
reentrancy-safe. However, depending on the memory model, the
compiler still won't use the actual hardware stack, but uses a
virtual emulated stack in either the `idata' area (small memory
model) or the `xdata' area (large memory model).

You are right that most compilers for the larger 16- or 32-bit system will
normally use the stack. However, the 8051 has a tiny
stack and no efficient addressing mode to obtain information from
the stack. This makes it more efficient to store parameters at
fixed memory locations at the cost of no longer being reentrancy-
safe.

Regards,
Joris
Joris van der Sande
2001-02-15 21:10:10 UTC
Permalink
Hi Rod,

Sorry, let me emphasize that I am not trying to criticise you,
I am just trying to make sure people get the right idea about
reentrancy...
Post by Rod Boyce
int FnDivide( int param1, int param2 )
{
return( param1 / param2 );
}
I believe I used this as an example to describe a re-entrant
function. I can assure you that on any stack based system
(not the 8051) this function would be re-entrant like I said
in the following text this probably will not work with the
SDCC (or the Keil compiler for that matter) on the 8051.
In fact, on a stack-based system _any_ function is reentrancy-
safe! Therefore, your example doesn't illustrate much, as you
could have shown _any_ arbitrary function!

I can only repeat myself: a compiler that generates non-stack-
based code (for example SDCC), will use fixed memory locations
to store local variables. A compiler that uses the stack will
simply allocate room on the stack for local variables and will
therefore be automatically reentrant. The SDCC compiler
however, needs to be told when it should use the stack for
allocating local variables, by specifying the `reentrant'
keyword.

Perhaps you were trying to illustrate reentrant code (contrary
to reentrancy-safe code). Then you could show a function that
calls itself, for example:

int fac(int n) reentrant
{ if (n == 1)
{ return 1 ;
} else
{ return n * fac(n-1) ;
}
}
PS I haven't touch an 8051 for about 18 months now. I am
mainly working on embedded PowerPC & 68HC11 chips these days
(new job new processor).
Good for you! Must be a great relieve to jump from an ancient
8-bit processor with segmented memory and a tiny stack to a
huge, fast 32-bit PowerPC! Even the 68HC11, although being
just 8-bit, is much easier to handle with its nice linear
memory...

...why was I using the 8051 again? :-)

Regards,
Joris

P.S. Just to be complete, here is a quote from the relevant
Automatic (local) variables and parameters to functions can
either be placed on the stack or in data-space. The default
action of the compiler is to place these variables in the
internal RAM ( for small model) or external RAM (for Large
model). They can be placed on the stack either by using the
--stack-auto compiler option or by using the 'reentrant'
keyword in the function declaration.
eg
unsigned short foo( short i) reentrant {
...
}
Note that when the parameters & local variables are declared
in the internal/external ram the functions are non-reentrant.
Since stack space on 8051 is limited the 'reentrant' keyword
or the --stack-auto option should be used sparingly. Note the
reentrant keyword just means that the parameters & local
variables will be allocated to the stack, it DOES NOT mean
that the function is register bank independent.
When compiled with the default option (i.e. non-reentrant ),
local variables can be assigned storage classes and absolute
addresses.
eg
unsigned short foo() {
xdata unsigned short i;
bit bvar;
data at 0x31 unsiged short j;
...
}
In the above example the variable i will be allocated in the
external ram, bvar in bit addressable space and j in internal
ram. When compiled with the --stack-auto or when a function
is declared as 'reentrant' local variables cannot be assigned
storage classes or absolute addresses.
Parameters however are not allowed any storage class,
(storage classes for parameters will be ignored), their
allocation is governed by the memory model in use , and the
reentrancy options.
Loading...