[net.micro.amiga] making reentrant code for "resident" programs

gnu@hoptoad.uucp (John Gilmore) (08/12/86)

In article <1478@amiga.amiga.UUCP>, jimm@amiga.UUCP (James D. Mackraz) writes:
> 2) Perhaps the Lattice C Compiler can create re-entrant code.

There is no way an average C program can get by without using global
variables (eg errno, the standard-I/O file tables, etc).  This means
that a facility to let programs be "reentrant", which does not provide
for separate data areas for each copy of the running, is foolhardy in a
portable C language environment.

(It's not clear that this is specific to C.  Know any programs that
have NO global variables and NO local static variables?)

A properly written compiler can support reentrancy -- even in a system
without memory management -- by making global data references relative
to an address register (rather than using the slow, cumbersome absolute
addressing mode most compilers use).  I don't know of any that do this,
however, since there are complications involved.
-- 
John Gilmore  {sun,ptsfa,lll-crg,ihnp4}!hoptoad!gnu   jgilmore@lll-crg.arpa
		     May the Source be with you!

higgin@cbmvax.cbm.UUCP (Paul Higginbottom) (08/13/86)

In article <969@hoptoad.uucp> gnu@hoptoad.uucp (John Gilmore) writes:
>In article <1478@amiga.amiga.UUCP>, jimm@amiga.UUCP (James D. Mackraz) writes:
>> 2) Perhaps the Lattice C Compiler can create re-entrant code.
>
>There is no way an average C program can get by without using global
>variables (eg errno, the standard-I/O file tables, etc).

That's if you're using <stdio.h> - true, to be portable you probably
would be, but often on the Amiga it makes more sense to use native AmigaDOS
calls.

>A properly written compiler can support reentrancy -- even in a system
>without memory management -- by making global data references relative
>to an address register (rather than using the slow, cumbersome absolute
>addressing mode most compilers use).  I don't know of any that do this,
>however, since there are complications involved.

Well, it just so happens there is one that does it this way!  Manx's Aztec
C uses register a4 as a segment register, when using the (default) small
model mode (which doesn't limit you to 64K code, by the way, just 64K of
global data - pretty unlikely!).  So the Manx system COULD be modified to
have each call to a program initialize a4 with another segment by going
through the seglist of the program, and then just tacking another on the
end.  It would be work, but not a massive amount I don't think.  This was
accomplished nicely on a UNIX-like operating system I worked with - rather
than re-entrancy, this idea is shared images.

>-- 
>John Gilmore  {sun,ptsfa,lll-crg,ihnp4}!hoptoad!gnu   jgilmore@lll-crg.arpa
>		     May the Source be with you!

Paul Higginbottom {caip|seismo|ihnp4}!cbmvax!higgin (I think)
			May the Fource be with you!

Disclaimer: I do not work for Commodore and my opinions are my own.

ingoldsby@calgary.UUCP (Terry Ingoldsby) (08/13/86)

In article <969@hoptoad.uucp>, gnu@hoptoad.UUCP writes:
> In article <1478@amiga.amiga.UUCP>, jimm@amiga.UUCP (James D. Mackraz) writes:
> > 2) Perhaps the Lattice C Compiler can create re-entrant code.
> 
> There is no way an average C program can get by without using global
> variables (eg errno, the standard-I/O file tables, etc).  This means
> that a facility to let programs be "reentrant", which does not provide
> for separate data areas for each copy of the running, is foolhardy in a
> portable C language environment.
> 
> (It's not clear that this is specific to C.  Know any programs that
> have NO global variables and NO local static variables?)
> 
> A properly written compiler can support reentrancy -- even in a system
> without memory management -- by making global data references relative
> to an address register (rather than using the slow, cumbersome absolute
> addressing mode most compilers use).  I don't know of any that do this,
> however, since there are complications involved.
> -- 
> John Gilmore  {sun,ptsfa,lll-crg,ihnp4}!hoptoad!gnu   jgilmore@lll-crg.arpa
> 		     May the Source be with you!


If I'm not mistaken, the `C' Compilers written for the OS9 operating system
do generate re-entrant code in the manner described by John Gilmore.

cc1@pegasus.cs.ucla.edu (Michael Gersten) (08/15/86)

This is similar to what someone suggested a while back, namely having a
program consist mostly of library routines so they would be shared.

The benefit of arrainging the program as library routines is that
A. They get kicked out of memory when needed
B. They can use globals
How? Simple. First, when a task does an open library, the open routine
allocates a block for that tasks globals. Second, all references in the
source to globals are macro's that expand to a subroutine call. Third,
all routines that use globals are surrounded by forbit/permit pairs.

This allows all parts of a program that don't do Wait() to be put in as
libraries.

			Michael Gersten
      Views expressed here may not be those of the Computer Club, UCLA, or
  anyone in their left OR right mind.  And that's the name o' that tune.

mykes@3comvax.UUCP (Mike Schwartz) (08/19/86)

In article <576@curly.ucla-cs.ARPA> occ4mgk@oac.ucla.edu, cc1@pegasus.UUCP (Michael Gersten) writes:
>This is similar to what someone suggested a while back, namely having a
>program consist mostly of library routines so they would be shared.
>
>The benefit of arrainging the program as library routines is that
>A. They get kicked out of memory when needed
>B. They can use globals
>How? Simple. First, when a task does an open library, the open routine
>allocates a block for that tasks globals. Second, all references in the
>source to globals are macro's that expand to a subroutine call. Third,
>all routines that use globals are surrounded by forbit/permit pairs.
>
>This allows all parts of a program that don't do Wait() to be put in as
>libraries.
>
>			Michael Gersten
>      Views expressed here may not be those of the Computer Club, UCLA, or
>  anyone in their left OR right mind.  And that's the name o' that tune.


First, I would like to submit that 'C' programs are not reentrant enough
for the Resident command, simply because of Initialized variables alone.
Consider a program that declares an initialized Window structure and
then modifies some of the structure's elements.  2nd time the program is
jmp'ed to, the initialized data hunks are not initialized anymore.  There
is a solution, and that is to have the Resident command handler copy the
initialized data hunks to a safe place (unknown about by the program), and
then each invocation it would have to initialize the program's known about
hunks...  It is possible, but kinda messy.

Now that I have a 1.5 MB amiga, I can possibly give some food for thought
about CLI's and libraries (more memory really makes a difference folks).

Who cares about Amiga-style libraries?  I think that there is a much easier
way to do things.  What happens if you had a hybrid library/device kind
of PROGRAM.  By program, I mean a 'C' program that you RUN from your
startup-sequence.  Such a 'C' program would not open any windows or printf
to the default screen or anything.  All it would do is create a message port
so that any user's of the thing could send it messages.  It only needs to
process two kinds of messages: Kill yourself, and What is your address?
The purpose of the first message is obvious - to reclaim memory.  The
second tells the user program the address of a jump table to get to
the library routines.  Since the routines themselves can be written in 'C',
the calling program can declare ALL of it's own memory and pass addresses
to the routines in the jump table.  

To remove the need to set up the jump table in assembler language, a
pointer to an array of functions can be passed and the functions called
directly from 'C' that way.  Note that as many user programs can call the
jump table routines at once, since it is fairly simple to make the library
routines re-entrant (not dependant on any global variables).  Each user
program has it's own stack, the subroutines can allocate all the variables
they want to off the caller's stack and still be re-entrant.

One word of caution:  PROCESSES can call such library routines which call
AmigaDos.  TASKS can not call library routines that call AmigaDos.  

OK, so now for my latest CLI idea...  Make a library as above.  Each CLI
(multiple CLIs can be birthed as in AMigaDos) opens its own window/screen
and console devices as desired.  These CLIs can use Andy Finkel's demo
code to alter the CLI IORequest to point to his own window (thanks again
and again Andy).  The main library/device/program should probably service
one last type of message: Execute() the passed program stri.  This should
be the only DOS call ever needed by a CLI.  Don't forget that Execute()
creates a new CLI, so whatever program you run CAN call AmigaDos and do
directories and whatever.  Now, these CLIs can have menus and gadgets and...
and ... and ... and ... and (everything you want that AmigaDos doesn't 
have)!

How about going one step further?  How about a CLI-WORKBENCH?  What if
you automatically assign a predetermined image to each of the obvious
file types (.i, .c, .asm, .a68, .a, .o, .h, ...).  You run the program, and
it does a directory of the current directory and puts the icons on the
screen (using intuition images...).  Then the mouse could be used to select
any of these icons.  Selecting a .c file would invoke EMACS on that .c file.
Selecting a file without extension would run the program.  A .bat file
could mean to EXECUTE it.  You get the idea...

So much for all this Blue Sky stuff.  Later everyone.