[net.micro] What Unix needs is ...

young@uci-icse.ARPA (Michal Young) (04/16/85)

  Many recent messages have asserted or conceded weaknesses in the basic
design of Unix.  Let's get concrete and start listing operating system
properties and/or facilities that we want, and that Unix doesn't provide.

For starts:
  An operating system should provide a flexible and efficient method for 
processes to communicate.  The Unix `pipe' mechanism has the great advantage
of simplicity,  but it is not efficient for some kinds of interaction.  
For instance, consider the case of the C compiler divided into several 
passes that communicate via pipes.  One correspondent to this bboard suggested
that it should be reconstituted as a single monolithic process, but that 
would be a workaround rather than a solution.  If a stronger communication
system were available, which allowed for instance sending large data structures
by sending pointers (for instance, by mapping parts of the address space of 
one process into that of another), then you could have the modularity of the 
Unix small-process model with the efficiency of the monolithic approach.
  Most modern compiled languages have visibility rules based on nested 
scopes.  How hard would it be for an operating system to support similar
rules for address spaces of processes?

--Michal Young, UC Irvine 
  young@uci

jbn@wdl1.UUCP (04/23/85)

      While UNIX needs better interprocess communication, a shared-memory
facility will strongly limit the portability of programs, because the
semantics of the underlying machine will become much more visible to the user.
UNIX programs do not at present need to have the size of a unit of memory
allocation, the semantics of the memory management unit, or knowlege of the
number of CPUs in the system designed into them.  We should not force them to.
The pipe mechanism has the virtue of simplicity.  With pipes and intermediary
processes, elaborate multiprocess systems can be constructed; the fact that
this mechanism is slow reflects some design decisions made when memory was
very expensive.  Pipes are actually implemented as circular buffers in small
files; normally the I/O does not actually take place, but all the machinery
of the buffer cache is exercised for each pipe operation.  We should be able
to do better today.
      Pipes need to be redesigned and reimplemented.  A reimplementation 
along the following lines might be useful.

	1.  Opening a pipe acquires a suitable amount of memory which is
	    held until the pipe is closed.  Suitable system, process, and
	    user quotas may be applied if desired.

	2.  Pipes are implemented as circular buffers in system memory.

	3.  If a write to a pipe fulfils the following conditions,

	    -- after the write, less than one I/O buffer size of space
	       will be available in the pipe,

	    -- there is a process waiting on a read from the pipe,

	    -- the waiting process is otherwise ready to run, and

	    -- the reading process does not have a lower priority than the
	       writing process, 

	    then control should immediately pass to the reading process rather 
	    than returning to the writing process. 

	4.  If a read from a pipe fulfils the following conditions,

	    -- after the read, less than one I/O buffer size of space
	       will be in use in the pipe,

	    -- there is a process blocked on a write to the pipe,

	    -- the writing process is otherwise ready to run, and

	    -- the writing process does not have a lower priority than
	       the reading process,

	    then control should immediately pass to the writing process rather
	    than returning to the reading process.

     The effect of this will be to produce a much tighter relationship between
the reader and writer; simple producer-consumer relationships will not cause
cycling of the scheduler, although context switches will still be necessary.
This will produce almost the effect of a coroutine-type process switch, as
is used with good effect in Modula.  Yet none of this will be visible to the
user, except as improved performance.

     Not being in the business of modifying UNIX, I have no plans to implement
this.  But I would appreciate hearing from anyone who does.

						John Nagle

mwm@ucbtopaz.CC.Berkeley.ARPA (04/26/85)

John Nagle writes that shared memory would cause portability problems
even among machine that shared that shared memory model. He goes on to
suggest improvements to the pipe mechanism that, while being an
excellent performance enhancement, don't change the semantics, and hence
don't solve any of the basic problems with pipes.

First, the "problem" with shared memory:

>      While UNIX needs better interprocess communication, a shared-memory
>facility will strongly limit the portability of programs, because the
>semantics of the underlying machine will become much more visible to the user.
>UNIX programs do not at present need to have the size of a unit of memory
>allocation, the semantics of the memory management unit, or knowlege of the
>number of CPUs in the system designed into them.  We should not force them to.

All correct, except that the semantics of the underlying machine don't
need to become visible to the user, any more than they needed to become
visible for the sbrk system call. I haven't seen AT&T's implementation
of shared memory, but if the semantics aren't like (or better than) the
following, then something is badly broken:

	Two co-operating processes request shared memory,
	The system verifies that everything is kosher, and
	decides how much memory they have asked for.
	It then allocates a segment at least that big, and
	returns it to the processes.

Nothing at all needs to be known by the programs about the mmu for this
to work. The synchronization problem is still unsolved, but that's not
new for Unix. I'd suggest a call to lock/unlock a shared segment in
various ways. Once again, nothing about the semantics of the machine
need to be visible to the program. Of course, you can still hang
yourself, but Unix has never been good about protecting code from
itself - which is a good thing.

As for pipes, they may be sufficient, but they have two serious
problems. First, they only work between processes with a common ancestor
that planned for this event. Second, they are inadequate to handle the
problem of data that needs to selectively fed through a process more
than once. The common example of this is the command line to typeset a
matrix equation that has equation as elements (a common happening in
linear algebra):

	eqn filename | tbl | eqn | troff

So, while John's suggested changes to pipes would be nice, Unix still
needs a different IPC facility.

	<mike

sambo@ukma.UUCP (Inventor of micro-S) (04/26/85)

     Michal Young says:
> If a stronger communication system
> were available, which allowed for instance sending large data structures
> by sending pointers (for instance, by mapping parts of the address space of 
> one process into that of another), then you could have the modularity of the 
> Unix small-process model with the efficiency of the monolithic approach.
     It seems to me what Young might be wanting is some way of doing
coprocessing, and some way of sharing certain things between the processes,
both of which are supported by Modula-2.  Though there are pros and cons for
both Modula-2 and C, I think both these features are desirable in a language.
This, of course, would not solve the problem of combining tools,
each of which is a completely separate program, in a flexible manner.
-----------------------------------------
Samuel A. Figueroa, Dept. of CS, Univ. of KY, Lexington, KY  40506-0027
ARPA: ukma!sambo<@ANL-MCS>, or sambo%ukma.uucp@anl-mcs.arpa,
      or even anlams!ukma!sambo@ucbvax.arpa
UUCP: {ucbvax,unmvax,boulder,oddjob}!anlams!ukma!sambo,
      or cbosgd!ukma!sambo

	"Micro-S is great, if only people would start using it."

dave@soph.UUCP (Dave Brownell) (05/01/85)

I agree, it is hard to say UNIX lacks shared memory when I can use
it on this very (UNIX) machine!!

But the person who said that there are no machine-dependant semantics
was not thinking of multiprocessor environments.  Consider the case of
two CPUs on a bus; each one has a cache of some size, and each cache
has what I will call a "cache chunk size":  the size of the minimum
cacheable bit of memory.

The problem is simple:  suppose two processes, communicating with
shared memory, need to access locations N and N+X?  If they are
running on the two different CPUs, there is no way to determine whether
mutual exclusion has been achieved on the chunk of memory with location
N unless you know the cache chunk size.

To bring this to a concrete point, say you have two 68020 processors
and the data space is cached on longword boundaries (4 bytes).  If
processor A reads location 1000, and processor B reads location 1002,
even a lock on every byte would not detect the collision.  (Both bytes
are in the same longword.)  The programs need to know that hardware
exclusion operates in longword units.

Naturally, this crops up only in multiprocessor cached environments.
(Which we hope will become much more common...)

-- 
	Dave Brownell
	EnMasse Computer Corporation
	enmasse!dave@Harvard.ARPA
	{genrad,harvard}!enmasse!dave

kissell@spar.UUCP (Kevin Kissell) (05/03/85)

> The problem is simple:  suppose two processes, communicating with
> shared memory, need to access locations N and N+X?  If they are
> running on the two different CPUs, there is no way to determine whether
> mutual exclusion has been achieved on the chunk of memory with location
> N unless you know the cache chunk size.
>
> 	Dave Brownell

Per-CPU caches do present coherence problems in multiprocessor configurations.
There are two reasonably well-known methods for dealing with them.  The first
is to create an address subspace from which data may not be cached, and use
this space for modifiable shared structures.  The second method is to give
all caches in the system the means to monitor the activity of other caches,
so that a modification of (shared) data in a cache will cause the invalidation
of the corresponding data in all other caches.  Neither method requires any
knowledge of the size of cache lines between processors.  By cacheing only 
instructions, the 68020 avoids the problem altogether, unless you want to worry
about shared, self-modifying code ;-).

Kevin D. Kissell
Fairchild Advanced Processor Development
uucp: {ihnp4 decvax}!decwrl!\
                             >spar!kissell
    {ucbvax sdcrdcf}!hplabs!/