[net.unix-wizards] Switching run-time contexts

KIRK.TYM%office-2@sri-unix.UUCP (02/04/84)

From:  Kirk Kelley <KIRK.TYM@office-2>

I get the impression that a high overhead may be involved when switching runtime
contexts in UNIX.  For an extremely large hypertext system (AUGMENT) already 
implemented in a sophisticated procedure oriented compiled language (L10), we 
are thinking of compiling L10 I/O calls into machine code to emulate a C call on
the stdio library for standard I/O functions needed by programs written in L10.

I think this means having two different runtime contexts that get switched every
time a call to a C procedure, like fopen, is made.  So there are a variety of 
related questions here:

   * How much work do you have to do to safely launch a C-style call?  Is it 
   enough to save registers and use the right argument/result passing 
   conventions, or will it also require allocated storage management facilities,
   error handlers of some type, or other rather involved things? and if so, how 
   much work is it to emulate those facilities, and how heavy to maintain a 
   whole C runtime and "swap" it somehow? 

   * How will this affect the performance of applications written in L10 vs 
   having the whole thing written in C?

   * Would 4.2BSD behave significantly different than, say, System V?

   * How about VAX vs 68000?

   * How farest the existing applications that do this?

O unix wizards, we await your reply.

 -- kirk

gwyn%brl-vld@sri-unix.UUCP (02/05/84)

From:      Doug Gwyn (VLD/VMB) <gwyn@brl-vld>

Of course, the exact details of inter-language linkage depend on the
specific machine architecture and on choices made by the language
implementers.  For most, perhaps all, UNIX C systems the "run-time
context" is fairly simple:

A procedure compiled by C expects information passed in a stack frame,
which typically contains procedure-return address, pointer to previous
frame, arguments to procedure, saved registers from calling context
(except those specifically reserved for procedure return value).
"Automatic" (procedure invocation local) variables are often allocated
off the same stack, although this is not the only possible design.
"Static" and "extern" (global) data is allocated once at link time.

To successfully invoke a C procedure from another language, one needs
to ensure that the proper calling frame is set up; this is usually
fairly easy if there is a run-time stack, tricky otherwise.  The return
value of a C procedure is often passed in a general register, which is
likely to be simple to deal with too.

The main problem you encounter when using C library routines may be
external name conflicts at link time, especially since STDIO routines
invoke "read", "write", "open", etc. which may conflict with names
chosen by the other language user (or, less likely, by the language
run-time system implementor).  Most UNIX systems support mixed F77 & C
by making the assembly-level names generated for the same user-supplied
name distinct; e.g. "open" becomes _open from C and _open_ from F77.

C procedures require very little run-time support; you will probably
need to supply malloc() and free() to allocate and free chunks of
memory, since these routines are explicitly used by STDIO for buffer
allocation (they are not technically part of the run-time system, but
you will need them).  Errors from UNIX system calls are handled by
storing an error code into a global integer `errno' and returning a
characteristic value (normally -1) from the syscall procedure.  This
is pretty minimal error handling; UNIX System V math library routines
invoke a (user-supplied, if desired) matherr() routine upon error.

The C environments on the VAX for UNIX System V and 4.2BSD differ very
little.  Since the MC68000 architecture is much like that of a VAX, I
suspect that C/68000 run-time environment design is similar to C/VAX.

The bottom line, then, is that you should have little trouble using C
library routines from L10 if there are no global name conflicts with
ANYthing in the C library that might be (indirectly) linked in support
of the routines you explicitly invoke, if you provide a little call/
return linkage converter and malloc/free package, and if you have a
run-time stack compatible with normal C needs.

The execution cost of the interface to C is almost certain to be
insignificant compared with the I/O operation cost.

A very good discussion of C run-time requirements is in Bell Labs
Computing Science Technical Report # 102, "The C Language Calling
Sequence", by S. C. Johnson and D. M. Ritchie.  One used to be able
to get CSTRs for the asking from MH 2C-364 but I don't know if that
is still true.

mark@umcp-cs.UUCP (02/11/84)

You can look at the code C itself uses to set up the environment
it wants before calling the users "main" routine in
/usr/src/libc/csu/crt.s (at least on our 4.1bsd system).
10 lines of assembler does it.
Generally you won't have to do even this much--C carries around
no assumptions about the environment it is in except that there be a
stack.
-- 
Mark Weiser 		
UUCP:	{seismo,allegra,brl-bmd}!umcp-cs!mark
CSNet:	mark@umcp-cs 	ARPA:	mark@maryland