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!/