The basic question "Why does SPAWN not copy the parent's command table
and does not even allow this as ans option?" remains unanswered...
The reason it remains unanswered is that there really *is* no good answer to
it. This limitation is the result of poor design decisions made back at the
original design of VMS, coupled with turf battles within various VMS groups
several years later.
The original designers of DCL - including most prominantly Dave Cutler - did
not see any reason to provide a SPAWN-like capability at all. In fact, my
guess is that they thought it was a bad idea. DCL was partly a reaction to
the RSX MCR interface. MCR effectively SPAWN'ed *everything*. It's hard to
describe what MCR was like to someone who never used it. But its fast and
loose creation of processes (well, tasks, in RSX parlance) led to an inteface
only a true hacker could love. (If you're familiar with Unix shells, imagine
that there is no CTRL/C - only a CTRL/Z, which automatically does a bg for you
when you type it. Couple this with no process groups - reads and writes to
the terminal get all intermixed. In VMS terms, it's as if every command is
actually started using a SPAWN/NOWAIT.) Besides, at the time the only DEC
OS that had anything like SPAWN was TOPS-20 - and the politics of the situa-
tion pretty much guaranteed that if the TOPS-20 group liked an idea, the VMS
group would find *some* way to refuse to implement it.
SPAWN was added in VMS V3.0, as I recall. Much of the work on it came from
the RTL group. While the RTL group had closer connections with the VMS
group than almost anyone else, they were still viewed as outsiders. They
were able to get code added to DCL, but it was really an add-on, minimal
effort. Proper synchronization of access to the terminal, which required
changes in the terminal driver (owned by the VMS group) didn't appear until
V4.0 or so - and it's a bit flakey to this day. More to the point, the way
symbols and logicals were passed to the new process was and is a crock: They
get stuffed down a mailbox, 512 bytes at a time, using the simplest possible
protocol (send 512 bytes, wait for ACK, send 512 more, etc.). *That's* why
SPAWN is so slow - creating a new process may be slow on a computer scale of
things, but $CREPRC on even a loaded system is close to instantaneous from a
human point of view. But transfering all that data, with two process context
switches (themselves cheap, but they force you to compete for the CPU each
time) for every 512 bytes - yuch.
If SPAWN had been designed in rather than added on, a simple, much faster
interface could have been used. A memory-to-memory copy would do it - you
*know* you're copying all the information, you *know* the new CLI will
organize memory the same way; why send it piecemeal? Logical names, since
they are supported in the kernel rather than in DCL, couldn't have used the
same technique - but, again, if we assumed *design*, rather than random
grown, we could easily add a "copy logical name table" operation to the
logical name services, which again would be essentially a memory-to-memory
copy.
Finally, for command tables: The damn things are *already* disk sections.
All that would be necessary would be to make modified tables accessible as
*shared* sections. Then the new process could easily copy the whole table
itself. (Of course, this is only easy if you've got your hands on the whole
implementation - I'm not sure the current implementation could do it.) But
DCL doesn't do that, and copying the whole table via a mailbox would be way
too slow.
Of course, the *right* way to implement this stuff would be to support copy-
on-write sections, and then simply share the symbol tables, command tables,
and so on, marking them copy-on-write (i.e., duplicate if modified). But for
historical reasons, VMS doesn't support copy-on-write, only copy-on-reference.
Copy-on-reference could also be used for all the above - if the appropriate
manipulation of existing sections could be done, and if there were a willing-
ness to change DCL to allow it. But no....
I like VMS, but the persistence of some of its day-1 flaws after all these
years is a major annoyance.
-- Jerry
Some more on the history of SPAWN, from somebody who was closely involved
with its creation:
|>The original designers of DCL - including most prominantly Dave Cutler - did
|>not see any reason to provide a SPAWN-like capability at all. In fact, my
|>guess is that they thought it was a bad idea. DCL was partly a reaction to
|>the RSX MCR interface. MCR effectively SPAWN'ed *everything*. It's hard to
|>describe what MCR was like to someone who never used it. But its fast and
|>loose creation of processes (well, tasks, in RSX parlance) led to an inteface
|>only a true hacker could love. (If you're familiar with Unix shells, imagine
|>that there is no CTRL/C - only a CTRL/Z, which automatically does a bg for you
|>when you type it. Couple this with no process groups - reads and writes to
|>the terminal get all intermixed. In VMS terms, it's as if every command is
|>actually started using a SPAWN/NOWAIT.) Besides, at the time the only DEC
|>OS that had anything like SPAWN was TOPS-20 - and the politics of the situa-
|>tion pretty much guaranteed that if the TOPS-20 group liked an idea, the VMS
|>group would find *some* way to refuse to implement it.
Of course, the PDP-11 had to do things that way because of the address space
constraints--every task only had 64K of address space. Unix ran all programs
in separate address spaces for the same reason. When the architecture for
VMS was being drawn up, Dave and the other designers thought that, with a
32-bit virtual address space and four protection modes, there was no longer
any reason to run each program in a separate process, and that process creation
would therefore be an infrequent event. Hence the heavyweight process
design. VMS has had from day 1 the ability to create subprocesses, but
there wasn't seen to be any need for providing command line access to this
capability, nor any need to completely clone the context of a process, ala
fork() on Unix.
|>SPAWN was added in VMS V3.0, as I recall. Much of the work on it came from
|>the RTL group. While the RTL group had closer connections with the VMS
|>group than almost anyone else, they were still viewed as outsiders. They
|>were able to get code added to DCL, but it was really an add-on, minimal
|>effort.
SPAWN came about due to a request from DEC's Methods and Tools group (the
folks who brought you the DECset tools). We had a R&D project for an integrated
software development environment. One of our ideas was to provide a way for
software developers to have several things going on at once on their terminal
by running many programs, each in its own subprocess. Our IDE would provide
a way to manage these subprocesses and switch between them. For this to work
properly, we needed a way to propagate symbols and logical names from the
parent to the subprocesses when they were created. I prototyped a SPAWN
capability using command procedures and a very minor modification to
LOGINOUT (the only change was to add the capability to have a newly-created
subprocess run a command procedure before taking input from SYS$INPUT:; this
command procedure restored the symbols and logicals that the parent process
had previously written to a file). We then went to the VMS group and got a
commitment that this capability would be added to DCL in VMS V3. The RTL
group would at the same time add a LIB$ interface to the capability.
Unfortunately, the DCL developer got way behind schedule. VMS tried to back
out of their previous commitment, but we were successful in forcing them to
keep their promise and implement SPAWN in V3. Unfortunately, due to the time
constraints, the implementation was not as elegant as it might have been, and
it also was incomplete. Command definitions were one of the things not done
due to time constraints (SET COMMAND was also new with VMS V3; it hadn't
existed when we first agreed with VMS on the SPAWN functional requirements,
so it wasn't in the list of things SPAWN needed to do to satisfy Methods &
Tools).
|> Proper synchronization of access to the terminal, which required
|>changes in the terminal driver (owned by the VMS group) didn't appear until
|>V4.0 or so - and it's a bit flakey to this day. More to the point, the way
|>symbols and logicals were passed to the new process was and is a crock: They
|>get stuffed down a mailbox, 512 bytes at a time, using the simplest possible
|>protocol (send 512 bytes, wait for ACK, send 512 more, etc.). *That's* why
|>SPAWN is so slow - creating a new process may be slow on a computer scale of
|>things, but $CREPRC on even a loaded system is close to instantaneous from a
|>human point of view. But transfering all that data, with two process context
|>switches (themselves cheap, but they force you to compete for the CPU each
|>time) for every 512 bytes - yuch.
There isn't even any wait for ACK. The parent process goes into a loop stuffing
data into the mailbox. The only synchronization is provided when the mailbox
fills and the parent goes into RWMBX state. That is why you can't do a SPAWN
reliably if you turn system service resource wait mode off. If SSRWM is off,
the parent gets SS$_MBFULL if the mailbox fills and aborts the spawn operation.
|>If SPAWN had been designed in rather than added on, a simple, much faster
|>interface could have been used. A memory-to-memory copy would do it - you
|>*know* you're copying all the information, you *know* the new CLI will
|>organize memory the same way; why send it piecemeal? Logical names, since
|>they are supported in the kernel rather than in DCL, couldn't have used the
|>same technique - but, again, if we assumed *design*, rather than random
|>grown, we could easily add a "copy logical name table" operation to the
|>logical name services, which again would be essentially a memory-to-memory
|>copy.
DEC/SHELL, a port of the Unix Bourne shell to VMS as a native VMS CLI, did
exactly that. It created a global section that the parent and child both
mapped and moved the items to be propagated into it. The child still had to
call $CRELOG to create all the logical names, but it was still much faster than
the mailbox method that SPAWN uses.
|>Finally, for command tables: The damn things are *already* disk sections.
|>All that would be necessary would be to make modified tables accessible as
|>*shared* sections. Then the new process could easily copy the whole table
|>itself. (Of course, this is only easy if you've got your hands on the whole
|>implementation - I'm not sure the current implementation could do it.) But
|>DCL doesn't do that, and copying the whole table via a mailbox would be way
|>too slow.
If you've ever looked at the DCL source code, you'd realize that it's not
quite as easy as that. But with a bit of thought, an efficient design could
be done. The problem is, the VMS group has always found more important
things to do than make SPAWN fast.
|>Of course, the *right* way to implement this stuff would be to support copy-
|>on-write sections, and then simply share the symbol tables, command tables,
|>and so on, marking them copy-on-write (i.e., duplicate if modified). But for
|>historical reasons, VMS doesn't support copy-on-write, only copy-on-reference.
|>Copy-on-reference could also be used for all the above - if the appropriate
|>manipulation of existing sections could be done, and if there were a willing-
|>ness to change DCL to allow it. But no....
You can't do copy-on-write because of the VAX hardware. The way that copy-on-
write is implemented is to have the OS write-protect the c-o-w page, trap the
ACCVIO that occurs when the process writes to it, then create the copy at that
point and retry the failing instruction. But VAX has the PROBER instruction,
which nonprivileged code can use to test the writeability of a page. If PROBER
could be made to fault, so the OS could intercept it and lie about c-o-w
pages, you could implement c-o-w. But it doesn't fault. Implementing copy-
on-write would break programs that use PROBER to check for writeability of
memory. VMS could have got around this by, from day 1, stating that the use
of PROBER would be unreliable and you'd have to use a SYS$PROBER (which gave the
correct answer for c-o-w pages) instead. But they didn't, and now they and
we are stuck with no c-o-w, at least on VAX (Alpha has the appropriate
capabilities in the hardware to allow c-o-w to be implemented).
--PSW
[stuff about spawn deleted]
> You can't do copy-on-write because of the VAX hardware. The way that copy-on-
> write is implemented is to have the OS write-protect the c-o-w page, trap the
> ACCVIO that occurs when the process writes to it, then create the copy at that
> point and retry the failing instruction. But VAX has the PROBER instruction,
> which nonprivileged code can use to test the writeability of a page. If PROBER
> could be made to fault, so the OS could intercept it and lie about c-o-w
> pages, you could implement c-o-w. But it doesn't fault. Implementing copy-
> on-write would break programs that use PROBER to check for writeability of
> memory. VMS could have got around this by, from day 1, stating that the use
> of PROBER would be unreliable and you'd have to use a SYS$PROBER (which gave the
> correct answer for c-o-w pages) instead. But they didn't, and now they and
> we are stuck with no c-o-w, at least on VAX (Alpha has the appropriate
^^^^^^^^^^^^^^^^^^^^^^^^^
> capabilities in the hardware to allow c-o-w to be implemented).
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Good thing, too, because Windows NT needs it.
--
==============================================================================
Wayne Sewell |INET: wa...@tachyon.com
Tachyon Software Consulting |UUCP: uupsi!uupsi6!tachyon!wayne
P. O. Box 550937, Dallas TX 75355-0937 |Voice: (214)-553-9760, Fax: -553-0077
=============================================================================
Moe, holding out fingers:"Pick two." Curly:"One, two. <eye poke> Yeow!"