[comp.os.minix] Shared libraries with minix

hbetel@watserv1.uwaterloo.ca (Heather Betel) (05/24/91)

        First off, I have to appologize to the guy who  suggested
putting  the  library  into  the  kernel. My message reads like a
flame, and I didn't want that. Anyhow, please don't take offense,
and  I'll  try  not  to  write  follow-ups while I am still over-
reacting :-).
        To the issue at hand. The best place to start is  to  de-
fine some goals. The shared library is a way to:
        1) minimize wasted space  on  disk  from  duplication  of
	   binaries.
	2) minimize wasted memory from duplication of binaries.
        Obviously, we want to have all processes share  the  same
memory  image  of  the  libraries,  which is loaded from a single
file.
        This is where we all agree, but every one seems  to  have
stopped  here  at  defining golas. There is one more issue: MMUs.
(3)The final solution should not *REQUIRE* an  MMU,  but  (4)  it
should take advantage of one, if it is available.
        Rather than find a solution for non-MMU systems, then try
to adapt it, I think we should find an MMU-friendly solution, and
adapt IT to the non-MMU systems.
        I have a solution in mind, but I am not sure I  like  it.
It  works  beautifully  on MMU systems (I think), and is probably
pretty good on the 68k, but it seems impossible,  sick,  or  both
for the 8086.
        What I think we should do is put in another  system  call
that  is  passed  the  file  name  of a library. It will return a
pointer to the start of the library.
        On an MMU system, the loaded library can be  mapped  into
the  process'es  addressing space, and can also be shared between
programs (I *THINK* all MMUs let  you  share  pages  between  two
processes).
        On the 68K, this is exactly the same, except  every  pro-
cess gets the same pointer.
        On the 8086, however, this isn't  much  good.  We  either
have  to do a far call, or tack the libraries onto the end of the
code segment.  The former won't work with the existing  compiler,
and the latter does not meet goal number 2.
        So there you are. That is my solution. With the  8086,  I
would  get someone to rewrite the C compiler. Actually, that's my
summer project. Its my first compiler, and since all  I  have  is
lots  of  reference  books  to  go  on, it won't be great, but it
should be very readable. It SHOULD be an ANSI C compiler for any-
thing  I  want, but that may end up being too ambitious, so I can
say that it'll start out for the 8086, and I hope to move it over
to the 88k, and maybe the 68k on the way...
        Lastly, I should point out why *I*  don't  want  the  li-
braries in the kernel:
        a) it doesn't achieve goal #4. To me, that says it is not
a  very  well thought out solution. Mine goes a step further, and
works for most hardware, including some that DON'T have  an  MMU,
so  I  can state that THERE is a better solution than putting li-
braries in kernel.
        b) How do parameters get passed? The  library  MUST  have
access  to  all  processes' data space (can you feel your stomach
churn?) On an MMU, this means all dataspaces  for  all  processes
are mapped into the lib server's dataspace!
        c) How do you select which lib function  you  want?  This
could  very  well  end up looking like the IOCTL call, with about
200 functions being hung off a single integer.
        d) where do you draw the line  between  what  is  put  in
these  libraries,  and  what isn't? The pascal runtime library is
just as important as the C libraries. Are you  going  to  put  in
both?  How about the LISP, FORTH, ADA, etc libraries. How about C
libraries that aren't in libc.a? (eg:curses) The list could go on
forever...
        e) The original suggestion talks about putting in another
trap.   Why  do  that  when messages work? If we are going to use
message passing, we should use it  all  the  way.  Otherwise,  we
might  as  well  just start mapping all the system calls onto the
various interrupts available. That gives us  about  246  possible
system calls on the PC, or 16 on the 68k.


 
Richard Betel
-------------------------------------------------------------------------
In a world of steel and ferroconcrete, it takes a stainless steel rat
to hide between the walls.
-------------------------------------------------------------------------

hp@vmars.tuwien.ac.at (Peter Holzer) (05/24/91)

hbetel@watserv1.uwaterloo.ca (Heather Betel) writes:

>        To the issue at hand. The best place to start is  to  de-
>fine some goals. The shared library is a way to:
>        1) minimize wasted space  on  disk  from  duplication  of
>	   binaries.
>	2) minimize wasted memory from duplication of binaries.
>        Obviously, we want to have all processes share  the  same
>memory  image  of  the  libraries,  which is loaded from a single
>file.
>        This is where we all agree, but every one seems  to  have
>stopped  here  at  defining golas. There is one more issue: MMUs.
>(3)The final solution should not *REQUIRE* an  MMU,  but  (4)  it
>should take advantage of one, if it is available.

Agreed.

>        Rather than find a solution for non-MMU systems, then try
>to adapt it, I think we should find an MMU-friendly solution, and
>adapt IT to the non-MMU systems.

Agreed.

>        I have a solution in mind, but I am not sure I  like  it.
>It  works  beautifully  on MMU systems (I think), and is probably
>pretty good on the 68k, but it seems impossible,  sick,  or  both
>for the 8086.

I think it is just the other way round (although you have to change the
compiler on the 80x86)

>        What I think we should do is put in another  system  call
>that  is  passed  the  file  name  of a library. It will return a
>pointer to the start of the library.
>        On an MMU system, the loaded library can be  mapped  into
>the  process'es  addressing space, and can also be shared between
>programs (I *THINK* all MMUs let  you  share  pages  between  two
>processes).
>        On the 68K, this is exactly the same, except  every  pro-
>cess gets the same pointer.

How do you decide where to map your library into the processes' address
space? If you have two libraries and three processes, one of which uses
library A, one B, and one both, do A and B start at the same address in
all processes that use them? You will get large holes this way (which
doesn't matter much if you use paging anyway), and worse, your program
might grow beyond the address that is reserved for the first library.
On the other hand, if you use a different start address for the library
for every process you might have to relocate the library for each
process and thus you can't share the text image between processes. You
won't conserve memory space this way, only disk space.

On the 80x86 this is not a problem if you use far pointers for
passing data between libraries and far calls, and near pointers/calls
if you stay within a library, and on other machines you can simulate
this with base pointers, but I guess this makes either writing shared
libraries awkward or you have to play nasty tricks with the
compiler/linker (I once wrote a shared library for OS/2 -- yuck).

How are these problems solved on existing UNIXes with shared libraries?

--
|    _  | Peter J. Holzer                       | Think of it   |
| |_|_) | Technical University Vienna           | as evolution  |
| | |   | Dept. for Real-Time Systems           | in action!    |
| __/   | hp@vmars.tuwien.ac.at                 |     Tony Rand |

adamd@rhi.hi.is (Adam David) (05/25/91)

hbetel@watserv1.uwaterloo.ca (Heather [actually Richard] Betel) writes:

>        b) How do parameters get passed? The  library  MUST  have
>access  to  all  processes' data space (can you feel your stomach
>churn?) On an MMU, this means all dataspaces  for  all  processes
>are mapped into the lib server's dataspace!

The library must have access to the dataspace of the current process.
This is essentially the same as if the library routine is included
in the codespace of the process like we use now.

>        d) where do you draw the line  between  what  is  put  in
>these  libraries,  and  what isn't? The pascal runtime library is
>just as important as the C libraries. Are you  going  to  put  in
>both?  How about the LISP, FORTH, ADA, etc libraries. How about C
>libraries that aren't in libc.a? (eg:curses) The list could go on
>forever...

What about a general purpose standard library which various
language libraries then use. Most of the primitives and other
general operations could be shared between different language
libraries.

Libraries can be categorised: system, application, user libraries.
It is a good idea to standardise the interface to the libraries so
that people can write custom libraries for their own use or for
distribution which use the same library handling routines as the
system does.

>        e) The original suggestion talks about putting in another
>trap.   Why  do  that  when messages work?

It is a question of efficiency. It is not desireable for a library
routine which is called often in a tight inner loop to require a
message rendevous each time it is called. It is only the first time,
if the library section is not already present, that a message call
is necessary so that the library section can be brought in from disk.

--
Adam David.
adamd@rhi.hi.is

windy@shiva.informatik.rwth-aachen.de (Andrew John Stuart Miller) (05/27/91)

hbetel@watserv1.uwaterloo.ca (Heather Betel) writes:


>        First off, I have to appologize to the guy who  suggested
	.
	.
	(stuff about shared libraries deleted)
	.
	.	
>various interrupts available. That gives us  about  246  possible
>system calls on the PC, or 16 on the 68k.

Try looking at the manuals for SunOS 4.X or OS9 or Helios.

These operatin systems use different methods to perform such a task,
nut for different reasons

OS9 to save memory, so that all processes can be guaranteed to be memory for
    real time response. (No VM - better that way?)
    there is a cost in terms of restricting the addressing modes which the 
    compiler can generate/ programmer can use.

Helios to save memory, to prevent the poor user having to fit more than 1..2MB
    per transputer in order to run the compiler or do any other work.
    The transputer (stack machine) has even fewer registers that an 80x86,
    but the addressing modes available more than make up for this. This scheme
    is the most flexible from the compiler writers point of view.


SunOS 4 to reduce paging traffic (uses VM to do this)
	This has to run on 68020s with suns own MMU
			   68030s
			   sparcs

Then you will know all the problems that might await you and the ways to avoid them.
Andy Tannenbaum will probably object to the whole idea though.

I have been wanting to do this for a long time, but never seem to get round to it


Happy hacking!

Andrew Miller

--
--------------------------------------------------------------------------------
email: windy@strange.informatik.rwth-aachen.de
snail: Ruetscherstr 165  D-5100 Aachen
voice: 0049 (0)241 894-355 or 8021122

hbetel@watserv1.waterloo.edu (Heather Betel) (05/28/91)

In article <3186@krafla.rhi.hi.is> adamd@rhi.hi.is (Adam David) writes:
>hbetel@watserv1.uwaterloo.ca (Heather [actually Richard] Betel) writes:
>
>>        b) How do parameters get passed? The  library  MUST  have
>>access  to  all  processes' data space (can you feel your stomach
>>churn?) On an MMU, this means all dataspaces  for  all  processes
>>are mapped into the lib server's dataspace!
>
>The library must have access to the dataspace of the current process.
>This is essentially the same as if the library routine is included
>in the codespace of the process like we use now.
>
	Its different. A library server runs in its own space, but to
access your parameters, it has to map in YOUR memory as well. This is
NOT essentially the same as before. IN the nonshared system, the
library functions are in your code space, but then, they also aren't
shared!(the whole point of the argument)

>>        d) where do you draw the line  between  what  is  put  in
>>these  libraries,  and  what isn't? The pascal runtime library is
>>just as important as the C libraries. Are you  going  to  put  in
>>both?  How about the LISP, FORTH, ADA, etc libraries. How about C
>>libraries that aren't in libc.a? (eg:curses) The list could go on
>>forever...
>
>What about a general purpose standard library which various
>language libraries then use. Most of the primitives and other
>general operations could be shared between different language
>libraries.
>
>Libraries can be categorised: system, application, user libraries.
>It is a good idea to standardise the interface to the libraries so
>that people can write custom libraries for their own use or for
>distribution which use the same library handling routines as the
>system does.
>
	A) PASCAL uses different calling semantics than C. Standardise
that! :-)
	B) C uses a completely different system for formatted io than
PASCAL. It is probably quite a task to reconcile the two. But if you
manage that, then try to then reconcile the two with FORTRAN! If you
can do that, why are you using minix? You should be able to make your
fortunes in AI or something...

>>        e) The original suggestion talks about putting in another
>>trap.   Why  do  that  when messages work?
>
>It is a question of efficiency. It is not desireable for a library
>routine which is called often in a tight inner loop to require a
>message rendevous each time it is called. It is only the first time,
>if the library section is not already present, that a message call
>is necessary so that the library section can be brought in from disk.
>
	Like a trap is any better. Instead of trapping, then copying
data, you just trap, then copy data! No matter how you cut it, there
will be a form of message passing with minix. Chack out how a serial
interrupt is handled. This won't be faster.

Richard

tsarna@polar.bowdoin.edu (Tyler Sarna) (05/29/91)

Heather Betel didn't write:
> 
>         What I think we should do is put in another  system  call
> that  is  passed  the  file  name  of a library. It will return a
> pointer to the start of the library.
>         On an MMU system, the loaded library can be  mapped  into
> the  process'es  addressing space, and can also be shared between
> programs (I *THINK* all MMUs let  you  share  pages  between  two
> processes).
>         On the 68K, this is exactly the same, except  every  pro-
> cess gets the same pointer.

This is actually an almost perfect description of how shared
libraries work under Exec, the hunk of Amiga OS that deals with
multitasking and so forth. The Exec scheme is slightly fancier,
but the basic concept is the same. This scheme is very
attractive from a efficiency standpoint. It also allows the
library to be unloaded when no processes that use it are
running.

>         On the 8086, however, this isn't  much  good.  We  either

This is the main stumbling point. I don't see a clean way to dit
it on the 8086. IMHO, the solution is to rid the world of
8086's, but I don't think that suggestion will go over well here :-)

>         c) How do you select which lib function  you  want?  This
> could  very  well  end up looking like the IOCTL call, with about
> 200 functions being hung off a single integer.

A much simpler solution is to just have the functions at a
well-known offset from the lib pointer.

>         d) where do you draw the line  between  what  is  put  in
> these  libraries,  and  what isn't? The pascal runtime library is
> just as important as the C libraries. Are you  going  to  put  in
> both?  How about the LISP, FORTH, ADA, etc libraries. How about C
> libraries that aren't in libc.a? (eg:curses) The list could go on
> forever...

You've overlooked one ofthe main advantages of your own scheme!
The library name is specified at runtime. Pascal (LISP, Draco,
whatever) programs simply open the appropriate library by name.
If noone else is using it, the library is loaded. When the
program closes the library (as part of _exit), the library is
unloaded if the use count is zero. Unneeded libraries can be
removed from the system, and new ones added when required. New
versions of old libraries can be installed without recompiling
the programs that use them, too.

>         e) The original suggestion talks about putting in another
> trap.   Why  do  that  when messages work? If we are going to use
> message passing, we should use it  all  the  way.  Otherwise,  we

The reason for not doing this is the large performance hit
involved in copying the messages.

-- 
Tyler "Ty" Sarna                            tsarna@polar.bowdoin.edu

           "Death therapy, Bob. It's a guaranteed cure."

adamd@rhi.hi.is (Adam David) (05/31/91)

hbetel@watserv1.waterloo.edu (Heather [actually Richard] Betel) writes:

>In article <3186@krafla.rhi.hi.is> adamd@rhi.hi.is (Adam David) writes:
>>The library must have access to the dataspace of the current process.
>>This is essentially the same as if the library routine is included
>>in the codespace of the process like we use now.
>>
>	Its different. A library server runs in its own space, but to
>access your parameters, it has to map in YOUR memory as well. This is
>NOT essentially the same as before. IN the nonshared system, the
>library functions are in your code space, but then, they also aren't
>shared!(the whole point of the argument)

I was not clear enough. I meant conceptual sameness in the operation
of the program code (what gets done, not how it gets done), I am aware that
the implementation mechanism is markedly different and carries with it some
non-trivial issues.

The library server has temporary access to the dataspace of the client
which initiated the library call, because the library routine is executed
with the user and group ID of the client. The client process has temporary
access to the library codespace in order to access the library routine.

In fact an implementation is conceivable where all the server has to do
is notify the MM that the access is a valid library call and therefore
to be allowed. By restricting the codespace access to the current library
section during each library call, there is little to no danger of one process
treading all over another one due to a badly written library routine. This
would seem to require full message-passing though, unless the interaction
between library server and MM is very special.

>	A) PASCAL uses different calling semantics than C. Standardise
>that! :-)
>	B) C uses a completely different system for formatted io than
>PASCAL. It is probably quite a task to reconcile the two. But if you
>manage that, then try to then reconcile the two with FORTRAN!

I am talking about fundamental operations, and not calling conventions.
The language-dependent part is in the language-specific library and the
part which can be shared between languages is in the general (utility)
library.

>	Like a trap is any better. Instead of trapping, then copying
>data, you just trap, then copy data! No matter how you cut it, there
>will be a form of message passing with minix. Check out how a serial
>interrupt is handled. This won't be faster.

Maybe I misunderstood. I was under the impression that the trap handler
was guaranteed maximum priority which would be higher than normal IPC
messages.

>Richard

Adam

hbetel@watserv1.waterloo.edu (Heather Betel) (06/01/91)

In article <54886@nigel.ee.udel.edu> tsarna@polar.bowdoin.edu (Tyler Sarna) writes:
>
>This is the main stumbling point. I don't see a clean way to dit
>it on the 8086. IMHO, the solution is to rid the world of
>8086's, but I don't think that suggestion will go over well here :-)
>
	I beg to differ. If you'll just chip in to help me upgrade
from my 286 to , say, an 040 :-)

>
>[Misunderstanding Deleted]

	My discussion of IOCTL like calls and asking about which
libraries to include was to refute someone else\'s suggestion for
implementing shared libraries in what I beleive was a broken way. Read
my original post again. I think you were probably reading too fast (or
was I typing too fast?)

Richard (Not Heather) Betel.
(I am not a sibling! I am a free man!)

hbetel@watserv1.waterloo.edu (Heather Betel) (06/01/91)

In article <3216@krafla.rhi.hi.is> adamd@rhi.hi.is (Adam David) writes:
>hbetel@watserv1.waterloo.edu (Heather [actually Richard] Betel) writes:
>
>The library server has temporary access to the dataspace of the client
>which initiated the library call, because the library routine is executed
>with the user and group ID of the client. The client process has temporary
>access to the library codespace in order to access the library routine.
>
	My point is that this must happen even on MMU systems. On the
8086, your model is fairly simple, but under, say, an 040, the library
server is a different process, with a completely different memory
space. Mapping in the client's space, doing the work, then mapping it
out, for every call is expensive.

>
>I am talking about fundamental operations, and not calling conventions.
>The language-dependent part is in the language-specific library and the
>part which can be shared between languages is in the general (utility)
>library.
>
	Then what is the difference between the library functions and
system calls? You are just putting in another level of indirection!

>>	Like a trap is any better. Instead of trapping, then copying
>>data, you just trap, then copy data! No matter how you cut it, there
>>will be a form of message passing with minix. Check out how a serial
>>interrupt is handled. This won't be faster.
>
>Maybe I misunderstood. I was under the impression that the trap handler
>was guaranteed maximum priority which would be higher than normal IPC
>messages.
	The harddrive controller uses IPC. Are you going to give the
library server higher priority than the harddrive?

Richard (Not Heather) Betel
I am not just a Sibling! I am a free man!

klamer@mi.eltn.utwente.nl (Klamer Schutte) (06/03/91)

In <1991Jun1.043438.17038@watserv1.waterloo.edu> hbetel@watserv1.waterloo.edu (Heather Betel) writes:

>	My point is that this must happen even on MMU systems. On the
>8086, your model is fairly simple, but under, say, an 040, the library
>server is a different process, with a completely different memory
>space. Mapping in the client's space, doing the work, then mapping it
>out, for every call is expensive.

Either i don't understand the problem, Richards idea of an MMU is too
simple, or my idea of an MMU is too complex ;-)

It should be possible for an MMU (040 type) to have more than 3 segments
allowed to one process at one time. The segments which need to be in 
current address space, and not causing a trap are (IMHO):
1) user program. text, data (incuding bbs) and stack.
2) trap handler. At least text. Perhaps data. Stack?
3) Shared library code. At least text. Perhaps read-only data.

This makes 5-8 segments. The standard m68k MMU (Not on chip! ;-)
has 16 segments (from memory, from structured computer organisation,
Dr Tanenbaum, first edition). So no remapping on every call should be 
needed!

>	The harddrive controller uses IPC. Are you going to give the
>library server higher priority than the harddrive?

I hope so. The kernel harddrive driver might call library routines as well...

Klamer

-- 
Klamer Schutte			Tel: +31-53-892786	Fax: +31-53-340045
Faculty of electrical engineering -- University of Twente, The Netherlands
preferred: klamer@mi.eltn.utwente.nl   SMTP: klamer@utelmi01.el.utwente.nl

evans@syd.dit.CSIRO.AU (Bruce.Evans) (06/03/91)

In article <klamer.675935632@mi.eltn.utwente.nl> klamer@mi.eltn.utwente.nl (Klamer Schutte) writes:
>In <1991Jun1.043438.17038@watserv1.waterloo.edu> hbetel@watserv1.waterloo.edu (Heather Betel) writes:
>
>>...
>>space. Mapping in the client's space, doing the work, then mapping it
>>out, for every call is expensive.
>
>Either i don't understand the problem, Richards idea of an MMU is too
>simple, or my idea of an MMU is too complex ;-)
>
>It should be possible for an MMU (040 type) to have more than 3 segments
>allowed to one process at one time. The segments which need to be in 
>current address space, and not causing a trap are (IMHO):
>1) user program. text, data (incuding bbs) and stack.
>2) trap handler. At least text. Perhaps data. Stack?
>3) Shared library code. At least text. Perhaps read-only data.

With a decent MMU, the library code can be mapped into all processes at the
same time at some convenient address such as 0xC0000000. It is easy to set
up direct calls from user code to library code. With a 68000 and no MMU,
the same scheme will work (for calls) using some less convenient (small)
address. Even with an 8086, far calls could be used (near calls to stub
routines that make far calls - there is the major inconvenience that the
code segment will mess up the stack frame).

Relocation of data is much more difficult. How can shared code handle
different data addresses? Pointers take care of many cases. But what
happens deep in an fprintf call when a buffer has to be mallocated?
malloc needs a global variable to start from, and it is too much trouble
to add it to the fprintf interface. On systems with an MMU and on 8086's,
such variables can be put at conventional locations in low memory, e.g.,
at 0x40000000, 0x40000004, ... for the MMU case and 0, 4, ... for the
segmented (split I&D) case. For 68000 systems with no MMU, I don't see
a good way to tell where the are.
-- 
Bruce Evans		evans@syd.dit.csiro.au

tim@proton.amd.com (Tim Olson) (06/04/91)

In article <klamer.675935632@mi.eltn.utwente.nl> klamer@mi.eltn.utwente.nl (Klamer Schutte) writes:
| In <1991Jun1.043438.17038@watserv1.waterloo.edu> hbetel@watserv1.waterloo.edu (Heather Betel) writes:
| 
| >	My point is that this must happen even on MMU systems. On the
| >8086, your model is fairly simple, but under, say, an 040, the library
| >server is a different process, with a completely different memory
| >space. Mapping in the client's space, doing the work, then mapping it
| >out, for every call is expensive.
| 
| Either i don't understand the problem, Richards idea of an MMU is too
| simple, or my idea of an MMU is too complex ;-)
| 
| It should be possible for an MMU (040 type) to have more than 3 segments
| allowed to one process at one time. The segments which need to be in 
| current address space, and not causing a trap are (IMHO):
| 1) user program. text, data (incuding bbs) and stack.
| 2) trap handler. At least text. Perhaps data. Stack?
| 3) Shared library code. At least text. Perhaps read-only data.

The two of you appear to be looking at two slightly different ways to
support shared libraries with an MMU.  The big difference between them
is whether the compiler/linker supports PIC (Position Independant
Code) and Data, or not.  If PIC is supported (most commonly through
PC-relative branches and references in the code sections and
base-register+offset addressing in the data sections), then a single
physical copy of the library code could be mapped to any virtual
address and still run correctly.  The shared library code could then
be mapped at runtime.  This appears to be the method Mr.  Schutte is
discussing.

Mr. (Not Heather!?) Betel, on the other hand, appears to assume
non-PIC code/data.  One solution to this kind of library is to map it
into its own virtual address space, much like MM and FS, and create a
library server process out of it.  This would entail quite a bit of
overhead for sending messages to the server and/or copying data in and
out of the calling process' memory.

Another (albeit grungy!) possibility for non-PIC systems is to fix the
library's virtual addresses to well-known, otherwise unused virtual
memory locations, and compile the library to use those addresses (e.g.
printf() exists at 0xa0001234 in every process' address space).  Then,
the one physical copy of the library gets mapped to the same virtual
address in each process at runtime.  However, this type of
shared-library mapping quickly becomes impossible to use when frequent
changes to the libraries occur.



--
	-- Tim Olson
	Advanced Micro Devices
	(tim@amd.com)

feustel@netcom.COM (David Feustel) (06/04/91)

And the only simple solution to this problem is those damn segment
registers on the 386/486!
-- 
David Feustel, 1930 Curdes Ave, Fort Wayne, IN 46805, (219) 482-9631
EMAIL: feustel@netcom.com  or feustel@cvax.ipfw.indiana.edu

peterc@suite.sw.oz.au.sw.oz.au (Peter Chubb,-x27,6982322,3982735) (06/05/91)

From article <1991Jun4.041033.20792@dvorak.amd.com>, by tim@proton.amd.com (Tim Olson):
> 
> Another (albeit grungy!) possibility for non-PIC systems is to fix the
> library's virtual addresses to well-known, otherwise unused virtual
> memory locations, and compile the library to use those addresses (e.g.
> printf() exists at 0xa0001234 in every process' address space).  Then,
> the one physical copy of the library gets mapped to the same virtual
> address in each process at runtime.  However, this type of
> shared-library mapping quickly becomes impossible to use when frequent
> changes to the libraries occur.

Alternatively, have a vector of addresses of routines at some standard place 
in the system -- rather like the way AmigaDOS does things now.  It
goes (almost) without saying that the shared library code itself has
to be written to be reentrant.  The data area used has to be that
appropriate for the process calling the function.  In a MMU-based
system that's easy: data virtual addresses can start at zero (separate
i/d); in a non-MMU based system,  the calling convention will have to
include setting a pointer to the base of the process's data segment.
All data references by the library routine will then have to be
indirected off this pointer, preferably automatically by the compiler.

			Regards,

				- Peter Chubb

Softway Pty Ltd, P.O. Box 305, Strawberry Hills, NSW 2012, AUSTRALIA
Phone: +61 2 698 2322;       Fax: +61 2 699 9174;     Telex: AA27987
Internet: peterc@softway.oz.au	   UUCP: ...!uunet!softway.oz!peterc

PAZZINI%BRUFSM@cunyvm.cuny.edu (Marcelo Pazzini) (06/12/91)

On Tue, 4 Jun 91 09:10:33 GMT Tim Olson said:
>In article <klamer.675935632@mi.eltn.utwente.nl> klamer@mi.eltn.utwente.nl
>(Klamer Schutte) writes:
>hbetel@watserv1.waterloo.edu (Heather Betel) writes:
>| It should be possible for an MMU (040 type) to have more than 3 segments
>| allowed to one process at one time. The segments which need to be in
>| current address space, and not causing a trap are (IMHO):
>| 1) user program. text, data (incuding bbs) and stack.
>| 2) trap handler. At least text. Perhaps data. Stack?
>| 3) Shared library code. At least text. Perhaps read-only data.

I worked at a company which used a 68030 as the main processor, performing
its own Unix-like OS. It had up to 16 segments for each program. They use
one for text, one for data & stack, others for shared memmory, including
libraries. I guess it works fine.

>The two of you appear to be looking at two slightly different ways to
>support shared libraries with an MMU.  The big difference between them
 (stuff about position independant compiler)
>address and still run correctly.  The shared library code could then
>be mapped at runtime.  This appears to be the method Mr.  Schutte is
>discussing.

Well, I only propose my method for a MMU based hardware. I guess it is not
a good idea to add offsets at runtime. I would also say relocations at load
time isn't good, but it cannot be avoided without hardware memmory control,
say, in an 8088 (bleargh). I have the same problem on moving Minix for
Transputers because they have no MMU, no segment control, nothing!

>Another (albeit grungy!) possibility for non-PIC systems is to fix the
>library's virtual addresses to well-known, otherwise unused virtual
>memory locations, and compile the library to use those addresses (e.g.
>printf() exists at 0xa0001234 in every process' address space).  Then,
>the one physical copy of the library gets mapped to the same virtual
>address in each process at runtime.  However, this type of
>shared-library mapping quickly becomes impossible to use when frequent
>changes to the libraries occur.

It will not happen if you use a jump table at the top of the library. And you
can relocate it using a real Unix-like ld, with a scriptfile to do this.

Hope it be useful for you, because I am not implementing this stuff. ;-)

Marcelo Pazzini                                   (pazzini@brufsm.BITNET)

DELC - CT                                         The child is grown,
UFSM Campus                                       The dream is gone,
Santa Maria, RS                                   And I have become,
97119                                             COMFORTABLY... TEACHER.
BRASIL   (BRAZIL if you're out of here!)          (D.Gilmour, diff by me)