[comp.sys.mac.programmer] what the heck is "reentrant"?

tedj@hpcilzb.HP.COM (Ted Johnson) (07/29/88)

What is the definition of "reentrant" and "non-reentrant"   
subroutines/programs?

-Ted

kent@lloyd.camex.uucp (Kent Borg) (08/02/88)

Reentrant means the code can be reentered.  In other words, if a
subroutine is reentrant, then many different programs can use the
subroutine (function, procedure, etc.) at the same time without
interfering with each other.  The main concern is that variables from
one instance of the routine does not interfear with another instance.

Because there is no preemptive multitasking in the Mac, programs don't
have to worry about other applications running behind their backs.
But they DO have to wonder whether some evil VBI task is doing things
it shouldn't, they have to coexist with desk accesories, and other
applications that might be running under MultiFinder.

There is another concrete reentrancy concern in the current Macintosh
community: There could be an application on an AppleShare volume that
is accessed by several Macintoshes.  For this to work, AppleShare must
allow it (I think there is a bit somewhere...), and the application
must be reentrant.  For example, temporary data must be distinct: if
you choose Undo, someone else's text should not appear in your
document.  The application also should not modify any of it's
resources, for example, preferences should be stored in separate file,
with a name/location that will not interfere with other user's
instances.

Kent Borg
kent@lloyd.uucp
or
husc6!lloyd!kent

gillies@p.cs.uiuc.edu (08/04/88)

Here are a few common ways to make something NON-reentrant:

(1) Have a subroutine generate and execute its own assembly-language
instructions.  Two separate threads of execution might try to write
different instructions to the same place.

(2) Old Fortran linkage.  One of the first proposed ways of
implementing a subroutines was to "deposit & jump", e.g. deposit the
return location in a global (right before the subroutine
instructions), and then jump to the beginning of the subroutine.  if
two different threads of execution call the same subroutine at the same
time, then one will probably return to the wrong location.

Don Gillies, Dept. of Computer Science, University of Illinois
1304 W. Springfield, Urbana, Ill 61801      
ARPA: gillies@cs.uiuc.edu   UUCP: {uunet,ihnp4,harvard}!uiucdcs!gillies

mharper@hpindda.HP.COM (Michael J. Harper) (08/05/88)

The best example of reentrant code that I've come
across is an interrupt service routine.

Suppose you get an interrupt and you're running your
ISR.  If this ISR gets interrupted with the SAME
interrupt and the SAME ISR gets run again, both
invocations of the ISR must be able to complete
normally.  (Think of an ISR that increments a
counter for example.)  If both invocations of the
same code can complete normally, then the code
is "reentrant," i.e. it can be reentered without
adverse effects.

Michael J. Harper

engber@speedy.cs.wisc.edu (Mike Engber) (08/05/88)

In article <104700046@p.cs.uiuc.edu> gillies@p.cs.uiuc.edu writes:
>
>Here are a few common ways to make something NON-reentrant:
>...

An even simpler way to make a funtion NON-reentrant is to use
static variables.

Sometimes this is desired, like with a random number generator.

I've also heard that a lot of old Fortran progams rely on the fact that
their compilers do not generate reentrant code (i.e. they rely on all
variables being static) and that this is the main obsticle keeping the
Fortran standard from allowing recursion.

-ME

larryha@tekig5.PEN.TEK.COM (Larry Hattery) (08/06/88)

Reentrant routines only become an issue in a multitasking OS where a
routine may get suspended before it is finished and the same routine
gets called again by another task.  The same is true for routines
called by interrupt handlers.  Any time a routine can be called from
more than one place, conceptually, at the same time, it should be
reentrant.  This means that it must provide mutual exclusion around
any global resources it is using to insure that subsequent calls to
the same routine will not screw things up for the call that hasn't yet
completed.  Here, global also means static variables in the routine
itself since these refer to the same location from call to call.  Of
course, any stack based variables are private to a particular instance
of the call and do not need protection.  Mutual exculsion is generally
handled with semaphores, or more radically by disabling interrupts,
while in critical sections of a routine which would fail if the routine
were reentered at that point.

I'm excluding rescursive routines because they are by definition,
and presumably be design, reentrant.

-- 
Larry E. Hattery                        Tektronix Inc.
larryha@penguin.PEN.TEK.COM             M/S 47-704
Portable Instruments Division           PO Box 500
(503)627-1225 days                      Beaverton, OR 97077

jimc@iscuva.ISCS.COM (Jim Cathey) (08/06/88)

In article <104700046@p.cs.uiuc.edu> gillies@p.cs.uiuc.edu writes:
>Here are a few common ways to make something NON-reentrant:
>
>(1) Have a subroutine generate and execute its own assembly-language
>instructions.  Two separate threads of execution might try to write
>different instructions to the same place.

It is OK to generate and execute your own assembly-language instructions
provided you create them on the stack (since each invocation of the subroutine
gets its own stack frame).  On a 68020 you still must flush the cache after
you execute your routine or risk the wrath of the gods!

>(2) Old Fortran linkage.  One of the first proposed ways of...

Here's another (and I might add the easiest) way:

(3) Modifying global or static local variables (in C parlance).  (Unless you 
use semaphore techniques on them.)

+----------------+
! II      CCCCCC !  Jim Cathey
! II  SSSSCC     !  ISC Systems Corp.
! II      CC     !  TAF-C8;  Spokane, WA  99220
! IISSSS  CC     !  UUCP: uunet!iscuva!jimc
! II      CCCCCC !  (509) 927-5757
+----------------+
			"With excitement like this, who is needing enemas?"

ech@poseidon.UUCP (Edward C Horvath) (08/09/88)

> Nf-ID: #R:hpcilzb.HP.COM:730049:p.cs.uiuc.edu:104700046:000:808
> Nf-From: p.cs.uiuc.edu!gillies    Aug  3 18:44:00 1988


> Here are a few common ways to make something NON-reentrant:
...

It's actually pretty easy: anything which modifies a statically-allocated
variable potentially loses reentrancy.  Consider
	i := i + 1;
If one copy of the program loads i, then another copy runs through the
whole statement, then the first copy completes, i winds up incremented
only once.  This kind of thing is particularly nasty, couse you only get
interrupts in that 10-microsecond "window of vulnerability" when the
system is already deployed in the field :-)

=Ned Horvath=

ech@poseidon.UUCP (Edward C Horvath) (08/10/88)

> I'm excluding rescursive routines because they are by definition,
> and presumably be design, reentrant.

No, a recursive routine calls itself only at specific, presumably "safe" points
in its lifetime: operations that "look" atomic (like i := i+1) ARE atomic.  Such
routines may still not be reentrant.

=Ned Horvath=